天天看点

开发:用自定义控件来实现常用的标题栏1需求2自定义控件步骤

1需求

1)       大量界面都需要某个布局时,我们可能会使用include去引用某个布局文件,但缺点就是,include无法处理具体的响应事件。

2)       举个栗子,现在你想做一个标题栏,带Button(触发finish方法)、还有textView(显示标题),用include的话,你得在每一个界面都来对Button设置点击监听,然后在onClick()里写finish();然后再对textView.setText();

3)       以上是每个新手的泪。现在我们用自定义控件来擦掉眼角的翔

2自定义控件步骤

2.1准备好控件的布局

预览图:

开发:用自定义控件来实现常用的标题栏1需求2自定义控件步骤

文件名:view_title_with_back

<?xml version="1.0" encoding="utf-8"?>
<!-- 通用的标题栏布局视图 -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:background="#4B5F6A"
                android:gravity="center_vertical">

    <ImageView
        android:id="@+id/title_option_back"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_centerVertical="true"
        android:clickable="true"
        android:contentDescription="@null"
        android:paddingLeft="13dp"
        android:paddingRight="13dp"
        android:src="@drawable/back"/>


    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:gravity="center_vertical"
        android:singleLine="true"
        android:textColor="@android:color/white"
        android:textSize="20sp"/>

</RelativeLayout>
           

2.2创建控件类的构造

2.2.1意义

       我们在配置文件里直接写控件名,系统会调用控件的构造,所以我们可以在构造里搞点飞机:

1)       布局:高端人士会在这里各种draw,我就直接inflate上面的布局了(╮(╯▽╰)╭)

2)       作用:你个控件定义来干嘛的?这里就可以写了,比如本文,这个控件有个按钮(点击则关闭界面),和一个text(设置标题)

2.2.2返回按钮

LayoutInflater.from(context).inflate(R.layout.view_title_with_back,//想要加载的布局
                this);//this是给加载好的布局,再添加一个父布局
           
//(联想到adapter的inflate都写null的,百度下即可知道区别,不过这里写null会怎样我就懒得测试了)

        ImageView iv_back = (ImageView) findViewById(R.id.title_option_back);
        iv_back.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                ((Activity) getContext()).finish();
            }
        });
           

如上面代码所示,我们这里直接就把布局inflate进来,并且在里面找到返回按钮,并实现监听触发finish()方法; 按钮很简单,可是问题来了,我们的text怎么办呢? 首先可以肯定的是,我们同样可以在这里把textView给find出来,问题就是我们不知道具体的界面的text是什么。我们也不能接受走回include的老路——在每个Activity界面里再去设置,假如我们可以用普通的textView那样拥有text属性就好了,那我们可以直接配置! 下面就介绍自定义属性~~

2.3自定义属性

1)       创建属性配置文件

开发:用自定义控件来实现常用的标题栏1需求2自定义控件步骤
开发:用自定义控件来实现常用的标题栏1需求2自定义控件步骤

2)       创建属性

<declare-styleable name="myTitleView">
    <attr name="textTitle" format="string|reference" />
</declare-styleable>
           

name="textTitle"是你界面配置里要用的属性

format是格式,这里是字符串和引用都可以(想了解更多可以百度自定义属性的format)

3)       让控件来使用属性

这点好理解,比如textView里的text属性,你填了东西,但是textView这个类里对这个text属性的值取都不取,你填了也是无效的,所以同样的,我们要在自定义控件的类里,对我们这个自定义属性进行取值并使用

其实自定义还有另外个方案,并不用在attrs.xml里配置,不过相对来讲不够强大,但就是简单点,本文就也有贴但注释掉了;

现在可以完整的把这个自定义控件的代码贴出来了:

package com.lie.customviewdemo.view;

import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.lie.customviewdemo.R;

/**
 * Created by lie on 2015-11-19.
 * 普通标题,具有以下功能:
 *  1)具有点击触发finish的返回按钮
 *  2)可在配置文件里直接设置标题文字
 */
public class TitleLayout extends RelativeLayout {

    /**
     * 以下代码通过构造函数中引入的AttributeSet 去查找XML布局的属性名称,然后找到它对应引用的资源ID去找值
     * 介绍了两种方式,一种需要在attrs.xml里配置(自由度高),一种不需要
     * @param context
     * @param attrs
     */
    public TitleLayout(Context context, AttributeSet attrs) {
        super(context, attrs);

        /**
         * 以下代码需要在attrs.xml里设置你自己的属性,很灵活
         * 
         */
        TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.myTitleView);
        String titleText = a.getString(R.styleable.myTitleView_textTitle);//这里对应你自定义属性的总名字

        /**
         * 以下的直接用,不用另外在attrs配置
         * 
         */
//        int resouceId = attrs.getAttributeResourceValue(null,//第一个参数:命名空间名
//                "textTitle",//第二个参数:xml文件里设置的属性名,用的时候务必属性名要一致,前面不用加android:或者其他命名空间
//                -1);//第三个参数:默认值
//        String Text;
//        if (resouceId > 0) {
//            Text = context.getResources().getText(resouceId).toString();
//        } else {
//            Text = resouceId+"";
//        }

        LayoutInflater.from(context).inflate(R.layout.view_title_with_back,//想要加载的布局
                this);//this是给加载好的布局,再添加一个父布局(联想到adapter的inflate都写null的,百度下即可知道区别,不过这里写null会怎样我就懒得测试了)

        ImageView iv_back = (ImageView) findViewById(R.id.title_option_back);
        iv_back.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                ((Activity) getContext()).finish();
            }
        });
           
TextView tv_title = (TextView) findViewById(R.id.tv_title);
        tv_title.setText(titleText);
//        tv_title.setText(Text);

    }
}
           

完成上面的代码,那么这个控件就是一个:带有点击会finish的按钮、可以显示text的好标题了

2.4使用自定义控件

在下面这行代码再添加一行代码

xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:lie="http://schemas.android.com/apk/res-auto"
           

lie是命名空间,你喜欢叫啥都行; 后面的这么写就行了,我之前是直接定义到自定义控件这个类的包的位置的,不过as更推荐上面这么写,那更简单

<com.lie.customviewdemo.view.TitleLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        lie:textTitle="测试标题1"/>
           

搞定~~~~~~~~

后话:可能还有人说,即便这样还是接受不了,那可以考虑在baseActivity里添加带返回和可以设置标题的东西,不过暂时我还不打算研究这块,等弄会了再搬上来吧

继续阅读