android学习 自定义view(组合控件)

Posted 阿飞飞啊飞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android学习 自定义view(组合控件)相关的知识,希望对你有一定的参考价值。

项目地址:https://github.com/libo1223/androidStudy

做到后面感觉自己也做了不少东西了,每次到用的时候还是重新造轮子。于是这里准备写一个库专门用来当工具类。

顺便说一下今天的主题吧,android提供了不少的控件用于使用,但是有些控件用起来不是很顺心。而且有时候写布局的时候越写越多。这个时候可以自己自定义view来解决这个问题。当然,真要全自定义view那挺复杂的,今天记录一下简单的,把所有控件组合起来。

Android有个控件是底部导航栏,但是这东西真的不好用,加了一堆莫名其妙的动画。我到现在还不知道他的点击波纹动画怎么关,所以定个目标下次做一个底部导航栏的。这次稍微简单点,主要是对组合控件的操作和理解。

要定一个组合控件,首先就要先有一个布局。

在layout下创建一个xml文件,然后我在里面加了一个textview,下图中的button之后会移除。

<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <Space
        android:layout_width="10dp"
        android:layout_height="match_parent"/>

    <TextView
        android:id="@+id/toolbar_title"
        android:gravity="center_vertical"
        android:text="标题"
        android:layout_width="90dp"
        android:layout_height="match_parent"/>

    <LinearLayout
        android:id="@+id/lineraLayout_button_list"
        android:gravity="right|center"
        android:layout_marginRight="10dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">
        <Button
            android:id="@+id/toolbar_button_left"
            android:text=""
            android:layout_width="30dp"
            android:layout_height="30dp"/>
        <Space
            android:layout_width="10dp"
            android:layout_height="match_parent"/>
        <Button
            android:id="@+id/toolbar_button_right"
            android:layout_width="30dp"
            android:layout_height="30dp"/>

    </LinearLayout>
</merge>

如上述代码所述,这个布局的左边是一个textview,右边是一个linearlayout。我想要做的这个控件是一个头部导航栏,那么textview是标题,然后在linaerlayout可以随意添加别的控件,比如按钮。

然后创建一个继承Linearlayout的class。代码如下

public class NavToolBar extends LinearLayout {

    private String TAG = this.getClass().getSimpleName();

    private TextView titleLable;
    private Context context;

    public NavToolBar(final Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context = context;

        //设置布局
        LayoutInflater.from(context).inflate(R.layout.toolbar_layout,this,true);

        titleLable = findViewById(R.id.toolbar_title);

        //根据xml中的参数选择如何显示组件
        TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.ToolbarLayout);
        if(attributes != null){
//            boolean leftButtonVisible = attributes.getBoolean(R.styleable.ToolbarLayout_haveLeftButton, true);
//            if (leftButtonVisible) {
//                buttonLeft.setVisibility(View.VISIBLE);
//            } else {
//                buttonLeft.setVisibility(View.INVISIBLE);
//            }
//            boolean rightButtonVisible = attributes.getBoolean(R.styleable.ToolbarLayout_haveRightButton, true);
//            if (rightButtonVisible) {
//                buttonRight.setVisibility(View.VISIBLE);
//            } else {
//                buttonRight.setVisibility(View.INVISIBLE);
//            }
        }
    }

    //返回textview
    public TextView getTitleLable(){
        return titleLable;
    }

    //添加按钮
    public Button addButton(int dp, String text){
        final Button button = new Button(context);

        final int px = DPtoPX.dip2px(context,dp);
        button.setLayoutParams(new LinearLayout.LayoutParams(px,px));
        button.setMinimumHeight(0);
        button.setMinimumWidth(0);
        button.setText(text);
//        button.setBackground(R.drawable.ic_more);
//        button.setBackgroundResource(R.drawable.ic_more);

        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                Toast.makeText(context,"!"+"我是新来的,不要欺负我哦!",Toast.LENGTH_LONG).show();
            }
        });
        LinearLayout linearLayout = findViewById(R.id.lineraLayout_button_list);
        linearLayout.addView(button);

        return button;
    }

    //删除按钮
    public void delButton(Button button){
        LinearLayout linearLayout = findViewById(R.id.lineraLayout_button_list);
        linearLayout.removeView(button);
    }

}

关键地方都有注释。这样子一个简单的组合控件就完成了。开放两个接口出去,一个动态添加按钮,一个删除按钮。也满足了我的需求。

下面是怎么用。

final NavToolBar navToolBar = findViewById(R.id.nav_tool_bar);
        TextView textView = navToolBar.getTitleLable();
        textView.setText("导航栏");

        final Button button = findViewById(R.id.wheel_add_button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                button1223 = navToolBar.addButton(60,"bt"+buttons.size());
                buttons.add(button1223);
            }
        });
        Button button1 = findViewById(R.id.wheel_remove_button);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(buttons.size()>1){
                    navToolBar.delButton(buttons.get(1));
                    buttons.remove(1);
                }
            }
        });

这边提一下增加按钮的时候,我给了一个参数用于设定按钮大小,因为他这里只能用px的,为了适配,所以转换了一下。

组合控件的入门基本上到这里了。然后下面给他小小的升级一下。

我们使用别的控件时,可以直接在xml里给他设置属性,什么text值啊什么,这种如果在代码里去设置就很痛苦。那我们能不能给自己设置一些属性呢。当然是可以的。

首先在values下创建attrs.xml。

在其中添加

<declare-styleable name="ToolbarLayout">
        <attr name="titleLabel" format="string"/>
        <attr name="haveLeftButton" format="boolean"/>
        <attr name="haveRightButton" format="boolean"/>
        <attr name="buttonLeftBackground" format="reference"/>
        <attr name="buttonrightBackground" format="reference"/>
    </declare-styleable>

这些是属性名字,以及他的类型,比如titleLabel作为标题肯定要是String的吧。具体需要什么属性,自己要用到的时候可以去查一下。

然后添加了这些后需要去绑定到我们的组件中,可以看到之前有一句 TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.ToolbarLayout);  这句就是为了绑定属性,然后他后面的代码其实是用来获取设定xml的属性值来做处理。代码如下


TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.ToolbarLayout);
if(attributes != null){
            String title = attributes.getString(R.styleable.ToolbarLayout_titleLabel);
            titleLable.setText(title);
        }

注意这个ToolbarLayout_titleLabel,前一个表示刚刚设置的name,后一个表示他的属性。组合在一起才可以找到这个属性,然后把这个属性设置到textview上。就可以完成xml中的属性设置了。

 

组合控件基本上就到这里了,这里多说几句,本来这是一个很简单的东西,无奈官方文档写的不详细,寥寥数笔带过。百度中的教程又少,动不动就是理论,扯一堆,看了半天不知所云。所以这边出一下教程记录一下。如果对自定义view有深入兴趣的,包括绘图什么的,可以看官方文档。https://developer.android.google.cn/guide/topics/ui/custom-components

再多提一下,之前Android学习是记录序号的,但是这里的东西我都是想到一块就写一块,顺着循序反而会误导,而且也有发布时间,所以之后的android学习就不标号了。

以上是关于android学习 自定义view(组合控件)的主要内容,如果未能解决你的问题,请参考以下文章

Android自定义View之自定义组合控件

Android 自定义View 三板斧之一——组合现有控件

Android自定义View的三种实现方式

浅谈Android自定义View

一手遮天 Android

Android 自定义控件之继承ViewGroup创建新容器