案例分析:
- 继承自extends LinearLayout
public class MainTabBarView extends LinearLayout
- 实现3个方法
public MainTabBarView(Context context) {
this(context, null);
}
public MainTabBarView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public MainTabBarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
- 关于Android attr
详见:
Android 自定义view (一)——attr 理解 - 易术军 - 博客园 (cnblogs.com)
Android attr 是什么
(1)attr 的简单理解就是一个属性约束,约束具体属性字段的属性的数据类型(boolean、string、float…)
(2)attr的文件名称不是固定的,只是方便理解和规范,也可以是其他名称,比如arrt、aesa…
(3)其实我们经常在使用,比如我们界面的布局文件,从狭隘的方面理解只要用xml形式文件就涉及到约束,而attr就是其中 的一种约束文件(类似Schema)而已
Android attr 的作用
(1)attr 作用就是约束属性数据类型,xml资源文件中定义各种attr,指定attr的数据类型。
Android attr 的使用方式
(1) 在自定义View的构造函数中解析这些从XML中定义的属性值,将其存放到View对应的成员变量中
(2) 在layout文件中为自定义View的XML属性赋值
Android attr 的简单创建
(1)我们在res/values目录下新建了一个名为attrs_ysj.xml文件,文件名是什么不重要,只要是xml文件就行。
(2)我们在该文件中定义我们自定义View所支持的XML属性。
(3)由图可知该文件的根结点是<resources> </resources>,我们在根节点下可以添加多个子节点,在节点中通过name指定XML属性名称,通过format指定XML属性值的类型,如下图所示:
(4)format支持的类型有enum、boolean、color、dimension、flag、float、fraction、integer、reference、string。
(5)通过定义一个styleable,我们可以在R文件里自动生成一个int[],数组里面的int就是定义在styleable里面的attr的id。所以我们在获取属性的时候就可以直接使用styleable数组来获取一系列的属性。
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MainTabBarView);
全部代码
package com.example.musicprotectedmvvmf.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.appcompat.widget.AppCompatTextView;
import com.example.musicprotectedmvvmf.R;
import me.jessyan.autosize.utils.AutoSizeUtils;
/**
* Administrator
* 2023/1/5
*/
public class MainTabBarView extends LinearLayout {
public MainTabBarView(Context context) {
this(context, null);
}
public MainTabBarView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public MainTabBarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, @NonNull AttributeSet attrs) {
setOrientation(VERTICAL);
setGravity(Gravity.CENTER);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MainTabBarView);
AppCompatImageView icon = new AppCompatImageView(context);
icon.setImageDrawable(array.getDrawable(R.styleable.MainTabBarView_tabIcon));
icon.setLayoutParams(new ViewGroup.LayoutParams(AutoSizeUtils.dp2px(context, 40), AutoSizeUtils.dp2px(context, 40)));
int padding = AutoSizeUtils.dp2px(context, 4);
icon.setPadding(padding, padding, padding, padding);
icon.setBackgroundResource(R.drawable.sel_menu_main_tab_bg);
icon.setImageTintList(context.getColorStateList(R.color.sel_menu_main_tab_icon_tint));
addView(icon);
AppCompatTextView text = new AppCompatTextView(context);
text.setText(array.getString(R.styleable.MainTabBarView_tabText));
text.setTextColor(getResources().getColorStateList(R.color.sel_menu_main_tab_text_tint, context.getTheme()));
LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lp.setMargins(0, AutoSizeUtils.dp2px(context, 4), 0, 0);
text.setLayoutParams(lp);
text.setTextSize(14);
addView(text);
//回收 TypedArray,供以后的调用者重新使用
array.recycle();
}
}
引用
<com.example.musicprotectedmvvmf.view.MainTabBarView
isSelected="@{vm.selectedTabId==MainViewConstant.TAB_FIND}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{()->handlers.onClickTab(MainViewConstant.TAB_FIND)}"
android:padding="8dp"
app:tabIcon="@drawable/ic_main_tab_podcast"
app:tabText="发现" />