zoukankan      html  css  js  c++  java
  • 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学习就不标号了。

  • 相关阅读:
    做一名「技术掮客」去变现自己的技术
    又一流氓推广Microsoft Edge,我勒个去
    拿什么心情来阅读我的代码(程序员的必备心理技能)
    发现与研究的基石
    VBA小技巧
    从明天起,让我们做一名调包侠
    设计模式之“Observer”注疏#01
    mybatis-dynamic-query 3.0 更新
    TiDB入门(四):从入门到“跑路”
    利用typescript生成Swagger文档
  • 原文地址:https://www.cnblogs.com/afei123/p/13879160.html
Copyright © 2011-2022 走看看