android 常常需要动态添加布局例如:
需要后台返回的天数个数来动态添加布局,有一下几种写法:
方式1。 基于recycleView
recyclerView使用了基于mvvm和databinding的框架github地址
xml布局,通过后台返回天数的数量daySize显示多少个布局
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="me.tatarka.bindingcollectionadapter2.LayoutManagers"/>
<variable
name="viewCtrl"
type="com.example.example.dynamicAddLayout.DynamicViewCtrl"/>
data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center_horizontal">
LinearLayout>
<android.support.v7.widget.RecyclerView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
app:itemBinding="@{viewCtrl.viewModel.itemBinding}"
app:items="@{viewCtrl.viewModel.items}"
app:layoutManager="@{LayoutManagers.grid(viewCtrl.daySize)}">
android.support.v7.widget.RecyclerView>
LinearLayout>
layout>
对于recyclew的使用进行了一定的封装,方便重用
public class BaseRecycleViewCtrl {
public ObservableField viewModel =new ObservableField<>();
}
public abstract class BaseRecyclerViewVM extends BaseObservable{
/** 数据源 */
public final ObservableList items = new ObservableArrayList<>();
public interface OnItemClickListener{
void onItemClickListener(String dayStr);
}
OnItemClickListener listener;
//绑定布局页面
protected abstract void setItemBinding(ItemBinding itemBinding, int position, T item);
public OnItemBind itemBinding =new OnItemBind() {
@Override
public void onItemBind(ItemBinding itemBinding, int position, T item) {
setItemBinding(itemBinding,position,item);
}
};
public OnItemClickListener getListener() {
return listener;
}
public void setListener(OnItemClickListener listener) {
this.listener = listener;
}
}
控制类viewCtrl
public class DynamicViewCtrl extends BaseRecycleViewCtrl{
public ObservableInt daySize =new ObservableInt(3);
public DynamicViewCtrl(final List dayList){
//dayList是后台返回的天数列表,最多显示3个(后台有时也不靠谱,自己限制一下)
if(dayList.size()>=3){
daySize.set(3);
}else{
daySize.set(dayList.size());
}
//绑定布局和监听,由于没有itemClick需要自己在绑定一个(自己想要添加的话可以重写这个框架)
viewModel.set(new BaseRecyclerViewVM() {
@Override
protected void setItemBinding(ItemBinding itemBinding, int position, DynamicItemVM item) {
itemBinding.set(BR.viewCtrl, R.layout.add_item).bindExtra(BR.listener,getListener());
}
});
//设置监听,这个监听是自己设置的,对每一项都设置了点击在xml中
viewModel.get().setListener(new BaseRecyclerViewVM.OnItemClickListener() {
@Override
public void onItemClickListener(String dayStr) {
//单个选择改变背景,其他恢复原样
for(int i=0;i< viewModel.get().items.size();i++){
DynamicItemVM dynamicItemVM = (DynamicItemVM) viewModel.get().items.get(i);
if(dayStr!=null){
//如果选择的天数和点击传入的天数相等
if(dayStr.equals(dynamicItemVM.getDayStr())){
//设置已选择
dynamicItemVM.setSelectBackground(true);
}else{
dynamicItemVM.setSelectBackground(false);
}
}
}
}
});
//设置数据源
viewModel.get().items.clear();
for(int i=0;i<(dayList.size()>=3?3:dayList.size());i++){
DynamicItemVM vm =new DynamicItemVM();
vm.setDayStr(dayList.get(i));
if(i==0){
vm.setSelectBackground(true);
}else{
vm.setSelectBackground(false);
}
viewModel.get().items.add(vm);
}
}
}
动态添加的子布局文件
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="viewCtrl"
type="com.example.example.dynamicAddLayout.DynamicItemVM"/>
<variable
name="listener"
type="com.example.example.common.BaseRecyclerViewVM.OnItemClickListener"/>
data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:background="@{viewCtrl.selectBackground?@drawable/day_button:@drawable/day_button_line}"
android:text="@{viewCtrl.dayStr}"
android:onClick="@{()->listener.onItemClickListener(viewCtrl.dayStr)}"
android:textColor="@color/colorPrimary"
android:gravity="center"/>
LinearLayout>
数据model
public class DynamicItemVM extends BaseObservable{
private String dayStr;
private boolean selectBackground;
@Bindable
public String getDayStr() {
return dayStr;
}
public void setDayStr(String dayStr) {
this.dayStr = dayStr;
notifyPropertyChanged(BR.dayStr);
}
@Bindable
public boolean isSelectBackground() {
return selectBackground;
}
public void setSelectBackground(boolean selectBackground) {
this.selectBackground = selectBackground;
notifyPropertyChanged(BR.selectBackground);
}
}
方式2。直接添加布局
ObservableArrayList items=new ObservableArrayList<>();
//设置布局
LinearLayout linearLayout=new LinearLayout(binding.getRoot().getContext());
RecyclerView.LayoutParams params = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
linearLayout.setLayoutParams(params);
items.clear();
for(int i=0;i
//创建子布局
AddItemBinding itemBinding = DataBindingUtil.inflate(LayoutInflater.from(binding.getRoot().getContext()),R.layout.add_item,null,false);
DynamicItemVM dynamicItemVM = new DynamicItemVM();
dynamicItemVM.setDayStr(dayList.get(i));
if(i==0){
dynamicItemVM.setSelectBackground(true);
}else{
dynamicItemVM.setSelectBackground(false);
}
itemBinding.setViewCtrl(dynamicItemVM);
final int finalI = i;
itemBinding.text.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
for(int j=0;j
if(finalI ==j){
items.get(j).getViewCtrl().setSelectBackground(true);
}else{
items.get(j).getViewCtrl().setSelectBackground(false);
}
}
}
});
items.add(itemBinding);
linearLayout.addView(itemBinding.getRoot());
}
binding.layout.addView(linearLayout);
}