Projects often have UI layouts with high repetition rates and high similarity, such as the following:
These UIs might be embedded in lists, they might be on some pages, and they’re characterized by a lot of familiar items, but not many. There are many kinds of realization, such as RecycleView, write one by one in the layout, or make a layout, dynamic add in.
So here of course is a dynamic add into a layout to save trouble, then need to package. Here the layout uses LinearLayout, because it is linear, horizontal or vertical, more resistant to operation.
How to encapsulate, here is the use of adapter form, the advantage is that this way you can use data control layout, and can be universal. The e overall code is not very technical, which means very simple. Post the complete code below, feel useful can be removed to change the more functional things.
But there is a problem I do not quite understand, hope the big men guide, is the following Layout code into Kotlin, how to do generic. I don’t know. I’ll write it in Java for now.
public class LinearTagLayout extends LinearLayout
implements LinearTagAdapter.OnDataChangedListener {
private final float leftMargin;
private final float topMargin;
private final float rightMargin;
private final float bottomMargin;
private final float itemWeight;
private final LayoutParams defItemParams;
public LinearTagLayout(Context context) {
this(context, null);
}
public LinearTagLayout(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public LinearTagLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LinearTagLayout);
leftMargin = ta.getDimension(R.styleable.LinearTagLayout_item_left_margin, 0);
topMargin = ta.getDimension(R.styleable.LinearTagLayout_item_top_margin, 0);
rightMargin = ta.getDimension(R.styleable.LinearTagLayout_item_right_margin, 0);
bottomMargin = ta.getDimension(R.styleable.LinearTagLayout_item_bottom_margin, 0);
itemWeight = ta.getFloat(R.styleable.LinearTagLayout_item_weight, 0);
float itemWidth = ta.getDimension(R.styleable.LinearTagLayout_item_view_width, LayoutParams.WRAP_CONTENT);
float itemHeight = ta.getDimension(R.styleable.LinearTagLayout_item_view_height, LayoutParams.WRAP_CONTENT);
int itemGravity = ta.getInt(R.styleable.LinearTagLayout_item_view_gravity, -1);
defItemParams = new LayoutParams((int) itemWidth, (int) itemHeight);
defItemParams.topMargin = (int) topMargin;
defItemParams.leftMargin = (int) leftMargin;
defItemParams.rightMargin = (int) rightMargin;
defItemParams.bottomMargin = (int) bottomMargin;
if(itemGravity ! = -1) {
if (itemGravity == 0) {
defItemParams.gravity = Gravity.CENTER_VERTICAL;
} else if (itemGravity == 1) {
defItemParams.gravity = Gravity.CENTER_HORIZONTAL;
} else if (itemGravity == 2) {
defItemParams.gravity = Gravity.LEFT;
} else if (itemGravity == 3) {
defItemParams.gravity = Gravity.TOP;
} else if (itemGravity == 4) {
defItemParams.gravity = Gravity.RIGHT;
} else if (itemGravity == 5) {
defItemParams.gravity = Gravity.BOTTOM;
}
}
ta.recycle();
}
private LinearTagAdapter adapter;
private OnTagClickListener itemClickListener;
public void setAdapter(LinearTagAdapter adapter) {
this.adapter = adapter;
this.adapter.setOnDataChangedListener(this);
changeAdapter();
}
public LinearTagAdapter getAdapter(a) {
return adapter;
}
public void setOnItemClickListener(OnTagClickListener listener) {
itemClickListener = listener;
}
private void changeAdapter(a) {
if (adapter == null) return;
removeAllViews();
for (int i = 0; i < adapter.getCount(); i++) {
View tagView = adapter.getView(i, adapter.getItem(i));
tagView.setLayoutParams(defItemParams);
int finalI = i;
tagView.setOnClickListener(view -> {
if(itemClickListener ! =null) { itemClickListener.onTagClick(view, finalI); }});if(itemWeight ! =0) {
addView(tagView, new LayoutParams(0, LayoutParams.WRAP_CONTENT, itemWeight));
} else{ addView(tagView); }}}@Override
public void onChanged(a) {
changeAdapter();
}
interface OnTagClickListener {
void onTagClick(View view, int position); }}Copy the code
abstract class LinearTagAdapter<T>(private val list: MutableList<T> = mutableListOf()) {
private var listener: OnDataChangedListener? = null
fun submitList(list: MutableList<T>) {
this.list.clear()
this.list.addAll(list)
notifyDataChanged()
}
fun getCount(a): Int = list.size
fun getItem(position: Int): T? = list.getOrNull(position)
fun notifyDataChanged(a){ listener? .onChanged() }abstract fun getView(position: Int.data: T?).: View
fun setOnDataChangedListener(listener: OnDataChangedListener?). {
this.listener = listener
}
interface OnDataChangedListener {
fun onChanged(a)}}Copy the code
<declare-styleable name="LinearTagLayout">
<attr name="item_left_margin" format="dimension" />
<attr name="item_top_margin" format="dimension" />
<attr name="item_right_margin" format="dimension" />
<attr name="item_bottom_margin" format="dimension" />
<attr name="item_view_width" format="dimension" />
<attr name="item_view_height" format="dimension" />
<attr name="item_view_gravity" format="enum">
<enum name="CENTER_VERTICAL" value="0" />
<enum name="CENTER_HORIZONTAL" value="1" />
<enum name="LEFT" value="2" />
<enum name="TOP" value="3" />
<enum name="RIGHT" value="4" />
<enum name="BOTTOM" value="5" />
</attr>
<attr name="item_weight" format="float" />
</declare-styleable>
Copy the code
Usage:
layout? .adapter =object : LinearTagAdapter<String>(dataList) {
override fun getView(position: Int.data: String?).: View {
val view = ImageView(context)
view.adjustViewBounds = true
view.loadImage(data)
return view
}
}
Copy the code