1.简述
顾名思义,即xml文件中根布局使用RelativeLayout(同理其他布局控件), 内部使用其他View控件,布局摆放,组合成XxxView的原始布局。 然后,Java类继承根布局标签对应的容器类,覆写构造函数,并初始化各子View的变量。 是最常用、最稳妥、不易产生过度绘制、内存泄漏等问题。
2. 实践
2.1 编辑 组合View的UI
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_root"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/icon_arrow"
android:layout_width="24dp"
android:layout_height="30dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginTop="3dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="3dp"
android:src="@drawable/ic_baseline_arrow_forward_ios_24" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="16dp"
android:layout_marginEnd="6dp"
android:gravity="center"
android:lines="1"
android:maxLines="1"
android:paddingTop="6dp"
android:paddingBottom="6dp"
android:singleLine="true"
android:text="安全中心"
android:textColor="#808080"
android:textSize="14sp" />
</RelativeLayout>
2.2 res/values/attrs.xml 编写快捷属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CommonRowEntranceView">
<!-- 混合类型:颜色int值+引用类型 属性定义时可以指定多种类型值-->
<attr name="row_bg" format="color|reference" />
<attr name="row_txt_color" format="color" />
<!-- String -->
<attr name="row_txt" format="string" />
</declare-styleable>
</resources>
2.3 继承根标签布局类,获取属性、设置属性
package com.cupster.base_super_resource;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.RequiresApi;
public class CommonRowEntranceView extends RelativeLayout {
public CommonRowEntranceView(Context context) {
super(context);
initInnerView(context);
}
public CommonRowEntranceView(Context context, AttributeSet attrs) {
super(context, attrs);
initInnerView(context);
initAttrs(context, attrs);
}
public CommonRowEntranceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initInnerView(context);
initAttrs(context, attrs);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public CommonRowEntranceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initInnerView(context);
initAttrs(context, attrs);
}
RelativeLayout mRootLayout ;
TextView mTitle ;
ImageView mArrow;
private void initInnerView(Context context) {
LayoutInflater.from(context).inflate(R.layout.view_common_row_entrance, this, true);//此处应为关联true,否则报错
mRootLayout = findViewById(R.id.layout_root);
mArrow = findViewById(R.id.icon_arrow);
mTitle = findViewById(R.id.title);
}
private void initAttrs(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CommonRowEntranceView);
//取值
Drawable bgDrawable = typedArray.getDrawable(R.styleable.CommonRowEntranceView_row_bg);
int txtColor= typedArray.getInt(R.styleable.CommonRowEntranceView_row_txt_color, Color.parseColor("#808080"));
String title = typedArray.getString(R.styleable.CommonRowEntranceView_row_txt);
//使用
if (bgDrawable == null) {
mRootLayout.setBackgroundColor(Color.WHITE);
} else {
mRootLayout.setBackground(bgDrawable);
}
if (!TextUtils.isEmpty(title)) {
mTitle.setText(title);
}
mTitle.setTextColor(txtColor);
//释放资源
typedArray.recycle();
}
}
2.4 实际场景使用
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:orientation="vertical"
>
<com.cupster.base_super_resource.CommonRowEntranceView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:row_txt="安全中心"
app:row_txt_color="#404040"
app:row_bg="#f2f2f2"
/>
<com.cupster.base_super_resource.CommonRowEntranceView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:row_txt="清理缓存"
app:row_txt_color="#404040"
app:row_bg="#f2f2f2"
/>
<com.cupster.base_super_resource.CommonRowEntranceView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:row_txt="版本检测"
app:row_txt_color="#404040"
app:row_bg="#f2f2f2"
/>
<com.cupster.base_super_resource.CommonRowEntranceView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:row_txt="关于我们"
app:row_txt_color="#404040"
app:row_bg="#f2f2f2"
/>
</LinearLayout>
3. 细节注意
- Android的自定义View预览,需要在自定义View编写无误且编译过,才能直接在PreView窗口预览效果
- 建议属性名前面加前缀,如:row_xxxxx;规范 & 避免资源命名冲突
- 属性值的获取,注意使用对应的TypeArray方法获取,否则会坑了自己。
- 属性值对应的获取方法可参考Android自定义View(1):基础