android 自定义 View 之标题栏(三)

22 篇文章 0 订阅

前面已学习了两种自定义控件的实现,还没学习的同学可以学习下,学习了的同学也要去温习下,一定要自己完全的掌握了,再继续学习,贪多嚼不烂可不是好的学习方法,我们争取学习了一种技术就会一种技术,而且不光看了就算了,最好的方法就是看完我自己再练习下,再扩展下,在原来的基础上在添加一些东西,比如,增加一些功能实现等等。效果图:

今天我们打算学习下另外一种自定义控件,就是创建可重复使用的组合控件,那么问题来了: 
什么是可重复使用? 
就是在应用中,可以在多个地方共同使用一套代码。这样不仅能减少我们的工作量,而且还能保持应用风格的一致,这种应用最多最直接的体现就是统一风格样式的标题栏。 
那什么又是组合控件呢? 
组合控件,顾名思义就是多个控件组合在一起,相互协作共同完成某些特定的功能。

下面我们就针对app应用中风格统一的标题栏来开始我们的学习。

首先,既然是一组组合的控件,那就必须有一个可以来包含这些控件的容器,我们所接触的可以存放控件的容器很多,比如LinearLayout、RelativeLayout等等多种Layout,今天我们就选择RelativeLayout来做我们的容器。和以前一样,我们先定义一个CompositeViews类来继承RelativeLayout类,并重写它的构造方法,代码如下:

/**
 * 作者:chengxiangtong on 2016/11/10 17:15
 * 邮箱:528440900@qq.com
 * 复合视图--控件组合
 */

public class CompositeViews extends RelativeLayout {
    private TextView mTextViewleft;
    private TextView mTextViewcenter;
    private TextView mTextViewright;

    private LayoutParams mLayoutParamsleft;
    private LayoutParams mLayoutParamscenter;
    private LayoutParams mLayoutParamsright;

    private tabBarListener mTabBarListener;


    public CompositeViews(Context context) {
        this(context, null);
    }


    public CompositeViews(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CompositeViews(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);

    }

    private void init(Context context, AttributeSet attrs) {
        mTextViewleft = new TextView(context);
        mTextViewcenter = new TextView(context);
        mTextViewright = new TextView(context);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CompositeViews);

        //获取其他属性和背景颜色一样
        int colorleftBackgroundColor = typedArray.getColor(R.styleable.CompositeViews_leftTextBackground, 0);
        mLayoutParamsleft = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        mLayoutParamsleft.addRule(RelativeLayout.ALIGN_PARENT_LEFT, TRUE);
        mTextViewleft.setText("左左左");
        mTextViewleft.setBackgroundColor(colorleftBackgroundColor);
        mTextViewleft.setTextSize(22);
        addView(this.mTextViewleft, mLayoutParamsleft);

        int colorcenterBackgroundColor = typedArray.getColor(R.styleable.CompositeViews_centerTextBackground, 0);
        mLayoutParamscenter = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        mLayoutParamscenter.addRule(RelativeLayout.CENTER_HORIZONTAL, TRUE);
        mTextViewcenter.setText("标题栏");
        mTextViewcenter.setBackgroundColor(colorcenterBackgroundColor);
        mTextViewcenter.setTextSize(22);
        addView(mTextViewcenter, mLayoutParamscenter);

        int colorrightBackgroundColor = typedArray.getColor(R.styleable.CompositeViews_rightTextBackground, 0);
        mLayoutParamsright = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        mLayoutParamsright.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, TRUE);
        mTextViewright.setText("右右右");
        mTextViewright.setBackgroundColor(colorrightBackgroundColor);
        mTextViewright.setTextSize(22);
        addView(mTextViewright, mLayoutParamsright);

        setOnListener();
    }

    public void settabBarOnclcikLisenter(tabBarListener mtabBar) {
        mTabBarListener = mtabBar;
    }

    public void setOnListener() {
        mTextViewleft.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                mTabBarListener.mTextViewleftListener();
            }
        });
        mTextViewright.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                mTabBarListener.mTextViewrightListener();
            }
        });
    }

    public interface tabBarListener {
        void mTextViewleftListener();

        void mTextViewrightListener();
    }

}

自定义属性其实也是相当的简单,首先,我们现在资源文件res下values目录下新建一个attrs.xml文件(as自建),新建的attrs.xml是一个包含如下代码的文件:

<declare-styleable name="CompositeViews">
    <attr name="centerText" format="string"></attr>
    <attr name="centerTextSize" format="dimension"></attr>
    <attr name="centerTextColor" format="color"></attr>
    <attr name="centerTextBackground" format="color|reference"></attr>

    <attr name="leftText" format="string"></attr>
    <attr name="leftTextSize" format="dimension"></attr>
    <attr name="leftTextColor" format="color"></attr>
    <attr name="leftTextBackground" format="color|reference"></attr>

    <attr name="rightText" format="string"></attr>
    <attr name="rightTextSize" format="dimension"></attr>
    <attr name="rightTextColor" format="color"></attr>
    <attr name="rightTextBackground" format="color|reference"></attr>

</declare-styleable>

attr代表的是一个属性,它里面所包含name字段是这条属性名,通过该属性名可以获取以format的约束为真的属性值;formate是该属性的格式,分别包含string,dimension,color,reference等等,分别代表字符串,大小,颜色,引用。其他的大家可以自行学习resources所包含的属性,但是在使用是之前必须在指定引用第三方控件的命名空间,在跟布局文件中添加如下一行代码:

xmlns:app=”http://schemas.android.com/apk/res-auto”

app是我们第三方命名空间的名字,可以任意命名,我们在使用自定义属性时必须以它开头。请看代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <test.com.test.CompositeViews
        android:id="@+id/CompositeViews"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="@dimen/activity_horizontal_margin"
        app:centerTextBackground="@android:color/holo_blue_bright"
        app:leftTextBackground="@android:color/holo_purple"
        app:rightTextBackground="@android:color/holo_purple"/>
</LinearLayout>

我们是使用custom加上我们自定义属性里面<attr name="centerTextBackground" format="color|reference"></attr>

里的name值来动态设置属性值的,如:app:centerTextBackground="@android:color/holo_blue_bright"

在我们xml文件中已设定好属性值,那么该怎么显示出来呢?这个是需要通过一个类型组TypedArray来获取

的,它里面包含各种从AttributeSet属性集中获取属性的方法,所以我们修改上面的构造方法和 init(Context context, At

tributeSet attrs)方

法,如下所示:


private void init(Context context, AttributeSet attrs) {
        mTextViewleft = new TextView(context);
        mTextViewcenter = new TextView(context);
        mTextViewright = new TextView(context);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CompositeViews);


        //获取其他属性和背景颜色一样
        int colorleftBackgroundColor = typedArray.getColor(R.styleable.CompositeViews_leftTextBackground, 0);
        mLayoutParamsleft = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        mLayoutParamsleft.addRule(RelativeLayout.ALIGN_PARENT_LEFT, TRUE);
        mTextViewleft.setText("左左左");
        mTextViewleft.setBackgroundColor(colorleftBackgroundColor);
        mTextViewleft.setTextSize(22);
        addView(this.mTextViewleft, mLayoutParamsleft);


        int colorcenterBackgroundColor = typedArray.getColor(R.styleable.CompositeViews_centerTextBackground, 0);
        mLayoutParamscenter = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        mLayoutParamscenter.addRule(RelativeLayout.CENTER_HORIZONTAL, TRUE);
        mTextViewcenter.setText("标题栏");
        mTextViewcenter.setBackgroundColor(colorcenterBackgroundColor);
        mTextViewcenter.setTextSize(22);
        addView(mTextViewcenter, mLayoutParamscenter);


        int colorrightBackgroundColor = typedArray.getColor(R.styleable.CompositeViews_rightTextBackground, 0);
        mLayoutParamsright = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        mLayoutParamsright.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, TRUE);
        mTextViewright.setText("右右右");
        mTextViewright.setBackgroundColor(colorrightBackgroundColor);
        mTextViewright.setTextSize(22);
        addView(mTextViewright, mLayoutParamsright);


        setOnListener();
    }


代码解释:首先通过上下文context获取到属性存放到TypedArray 中,然后通过TypedArray 里封装好的各种方法获取对应的属性值,然后再分别为我们的控件设置属性。这样就完成了,自定义属性的使用,并且复用度高,每当需要使用标题栏是都只需要在xml中添加我们定义的View控件,为其配置属性即可使用,节约了开发时间,提高了效率,并且还保持的app风格的一致。
好,到这里感觉已经讲完了整个过程吧,其实还有一个重要的实现还没有讲。我们的控件已经可以呈现出来了,但是怎么完成里面控件的作用呢?
这里比较常见的做法是利用回调机制来实现功能的开发,首先我们先定义一个接口,创建两个方法,用于左右控件的点击事件。

把定义好的接口暴露给调用者

public void settabBarOnclcikLisenter(tabBarListener mtabBar) {
    mTabBarListener = mtabBar;
}

然后在构造方法中为左右控件添加点击事件,等待调用者自己实现:
public void setOnListener() {
    mTextViewleft.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            mTabBarListener.mTextViewleftListener();
        }
    });
    mTextViewright.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            mTabBarListener.mTextViewrightListener();
        }
    });
}

public interface tabBarListener {
    void mTextViewleftListener();

    void mTextViewrightListener();
}
谁调用,谁实现.在这里我们只在MainActivity中代码如下:

public class MainActivity extends AppCompatActivity implements CompositeViews.tabBarListener {

    private CompositeViews mCompositeViews;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout3);
        mCompositeViews = (CompositeViews) findViewById(R.id.CompositeViews);
        mCompositeViews.settabBarOnclcikLisenter(this);

    }

    @Override
    public void mTextViewleftListener() {
        Toast.makeText(this,"mTextViewleftListener",Toast.LENGTH_LONG).show();
    }

    @Override
    public void mTextViewrightListener() {
        Toast.makeText(this,"mTextViewrightListener",Toast.LENGTH_LONG).show();

    }
}

已经可以实现我们的需求了,下一篇是自定viewGroup

github地址:https://github.com/xiangtongcheng/customerView



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值