对于Android小伙伴来说,自定义View是一个初级程序员进阶中高级程序员所必需掌控的技能。
话不多说,接下来我们直接开始讲解:
自定义View按类型来划分的话,自定义View的实现方式大概可以分为三种:
- 组合控件
- 继承控件
- 自绘控件
今天这一篇我们讲解的就是组合控件。
- 定义标题栏布局文件
activity_common_title.xml
。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="50dp"
tools:context=".MainActivity">
<ImageView
android:id="@+id/ivBack"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="10dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:src="@drawable/ic_reply_black_24dp"/>
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:textSize="22dp"
android:textStyle="bold"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
- 抽取一个公共的BaseView
public class BaseView extends RelativeLayout {
protected Context mContext;
protected LayoutInflater mInflater;
public BaseView(Context context) {
this(context, null);
}
public BaseView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BaseView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
private void initView(Context context) {
mContext = context;
mInflater = LayoutInflater.from(mContext);
int resourceId = getResourceId();
if (resourceId > 0) {
View view = inflate(mContext, resourceId, this);
initView(view);
}
}
/**
* 获取布局文件
*
* @return
*/
protected int getResourceId() {
return 0;
}
/**
* 初始化布局
*
* @param view
*/
protected void initView(View view) {
}
public void destroyView() {
unbindDrawables(this);
}
/**
* @param view
*/
private void unbindDrawables(View view) {
if (null == view) {
return;
}
if (view.getBackground() != null) {
Drawable drawable = view.getBackground();
if (null != drawable) {
drawable.setCallback(null);
drawable = null;
}
}
if (view instanceof ViewGroup && !(view instanceof AdapterView)) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
unbindDrawables(((ViewGroup) view).getChildAt(i));
}
((ViewGroup) view).removeAllViews();
} else if (view instanceof ImageView) {
Drawable drawable = ((ImageView) view).getDrawable();
if (null != drawable) {
drawable.setCallback(null);
drawable = null;
}
}
view = null;
}
}
- 根据给定布局实现自定义View
public class CommonTitleView extends BaseView {
private ImageView mIvBack;//返回按钮
private TextView mTvTitle;//标题
private View.OnClickListener mLeftOnClickListener;
public void setLeftOnClickListener(OnClickListener mLeftOnClickListener) {
this.mLeftOnClickListener = mLeftOnClickListener;
}
public CommonTitleView(Context context) {
this(context,null);
}
public CommonTitleView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public CommonTitleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected int getResourceId() {
return R.layout.view_common_title;
}
@Override
protected void initView(View view) {
mIvBack = view.findViewById(R.id.ivBack);
mTvTitle = view.findViewById(R.id.tvTitle);
mIvBack.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mLeftOnClickListener.onClick(v);
}
});
}
// 设置标题
public void setTitle(String title){
mTvTitle.setText(title);
}
@Override
public void destroyView() {
super.destroyView();
}
}
- 在Activity的布局文件中添加CommonTitleView
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.hyq.customviewdome.view.CommonTitleView
android:id="@+id/cTview"
android:layout_width="match_parent"
android:layout_height="50dp"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
- 在Activity中操作CommonTitleView
class MainActivity : AppCompatActivity() {
private lateinit var cTview: CommonTitleView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
cTview = findViewById(R.id.cTview)
cTview.setTitle("自定义View")
cTview.setLeftOnClickListener { finish() }
}
}
效果图