项目中经常会有一些重复率高,相似度高的UI布局,比如下面的:
这些UI可能嵌在列表里,可能在一些页面中,他们的特点是有好多相识的 item,但又不会很多。实现也有很多种,比如用 RecycleView,在布局中一个个的写,又或者搞一个 layout,动态 add 进去。
那么这里当然是用动态 add 进一个 layout 省事了,那么就需要封装。这里layout用LinearLayout,因为他是线性的,可横可竖,比较耐操。
怎么封装,这里是使用 adapter 的形式,好处是这样可以用数据的方式控制布局,而且可以通用。整体代码技术含量不高,意思是很简单。。下面贴上完整代码,感觉有用的可以拿走改成功能更多的东西。。
不过有一个问题我不太懂,望大佬们指点一下,就是将下面 Layout 的代码转成 Kotlin ,泛型要怎么搞。不太懂,这里暂时先用 java 写了。
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() {
return adapter;
}
public void setOnItemClickListener(OnTagClickListener listener) {
itemClickListener = listener;
}
private void changeAdapter() {
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() {
changeAdapter();
}
interface OnTagClickListener {
void onTagClick(View view, int position);
}
}
复制代码
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(): Int = list.size
fun getItem(position: Int): T? = list.getOrNull(position)
fun notifyDataChanged() {
listener?.onChanged()
}
abstract fun getView(position: Int, data: T?): View
fun setOnDataChangedListener(listener: OnDataChangedListener?) {
this.listener = listener
}
interface OnDataChangedListener {
fun onChanged()
}
}
复制代码
<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>
复制代码
用法:
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
}
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END