【Android】初步接触自定义View

本篇博客以自定义一个TopBar为起点,来初步了解自定义View。

1. 定义View具有的属性

自定义View,首先需要定义该View所具有的属性。我们可以先建立一个xml文件,这里我们定义了一个叫atts的文件,在里面用了如下的代码来定义了TopView所需要的属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="Topbar">
        <attr name="title" format="string"/>
        <attr name="titleSize" format="dimension"/>
        <attr name="titleBackgroundColor" format="reference|color"/>
        <attr name="showLeftButton" format="boolean"/>
        <attr name="leftButtonText" format="string"/>
        <attr name="leftButtonBackground" format="reference|color"/>
        <attr name="leftButtonTextColor" format="color"/>
    </declare-styleable>
</resources>

属性的意思,根据属性名即可看出。
需要注意的是几个没有用到过的类型:

  • reference指的是引用类型,可以在这样的类型中指定引用的资源(如:@color/colorPrimary)
  • dimension指的是尺寸类型,可以用这样的方法来指定尺寸(如:32dp 24sp…)

这样,我们就把这个控件所需要的属性定义了出来。接下来,就是编写我们定义的View的Java代码。

2. 映射刚刚定义的参数

我们这里定义了一个Topbar类,继承自RelativeLayout,这样便可以包含我们显示文字以及左边的按钮的TextView及Button。

然后我们会发现,需要给这个Topbar添加构造方法。它的构造方法有四种形式,如下图所示:

由于是初步涉足,我们先只说前两种,第一种构造方法是只有Context这一个参数的,第二个构造方法除此之外还多出了一个AttributeSet类型的参数,这个参数是用来保存我们控件所对应的属性的,所以我们选择第二个构造方法。

然后我们创建一个TypedArray对象,并用context的obtainStyledAttributes方法将控件的属性映射过来。

TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.Topbar);

之后,就可以开始处理我们的属性值。

TypedArray和Java中的Map比较像,是通过键值对的形式来存储对象的。对应属性的key是通过styleable的name(如这里的Topbar)通过下划线连接对应的属性的名字而成的。(如Topbar_title)

所以,我们可以通过TypedArray中对应的方法获取对应的参数(第二个参数是默认值)。

注意,使用完TypeArray后,要调用它的recycle方法对其进行回收,避免资源的浪费

   private String title;
   private Drawable titleBackgroundColor;
   private float titleTextSize;

   private String leftButtonText;
   private Drawable leftBackground;
   private int leftTextColor;

   title = typedArray.getString(R.styleable.Topbar_title);
   titleBackgroundColor = typedArray.getDrawable(R.styleable.Topbar_titleBackgroundColor);
   titleTextSize = typedArray.getDimension(R.styleable.Topbar_titleSize,14F);

   leftButtonText = typedArray.getString(R.styleable.Topbar_leftButtonText);
   leftBackground = typedArray.getDrawable(R.styleable.Topbar_leftButtonBackground);
   leftTextColor = typedArray.getColor(R.styleable.Topbar_leftButtonTextColor,0);

   typeArray.recycle();
3.为控件赋予传入的参数

处理完属性值后,我们便可以开始处理我们所需要用到的控件了。首先调用控件的new方法,并将上下文传入,来实例化我们的控件。

leftButton = new Button(context);

然后将我们自定义的属性,赋给我们的控件。

titleText.setText(title);
titleText.setBackground(titleBackgroundColor);
titleText.setTextSize(titleTextSize);

leftButton.setText(leftButtonText);
leftButton.setBackground(leftBackground);
leftButton.setTextColor(leftTextColor);

setBackground(titleBackgroundColor);
4. 将控件放入Layout中

之后,我们需要将我们的控件放入我们的Layout中,这里需要用到LayoutParams类。
首先,在它的构造方法中指定控件的宽、高。
然后,用addRule方法,为参数指定一些对应的参数(如:RelativeLayout.ALIGN_PARENT_LEFT),后面的是它的值,如TRUE
然后调用addView方法,将leftButton及leftParams传入。

private LayoutParams leftParams,titleParams;

leftParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE);
leftParams.addRule(RelativeLayout.CENTER_VERTICAL);
addView(leftButton,leftParams);
测试

在这里,我们测试下我们的Topbar能否正常显示,我们在activity_main中加入我们的控件。注意,引入控件时需要包含包名。


<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"
    android:orientation="vertical">
    <com.nullptr.viewdesign.Topbar
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:title="我的Topbar"
        app:titleTextColor="#eee"
        app:titleBackgroundColor="@color/colorPrimary"
        app:leftButtonText="返回"
        app:leftButtonBackground="@color/colorPrimary"
        app:leftButtonTextColor="#eee"/>
</LinearLayout> 

效果如图:

可以看到,成功地显示了Topbar。

5.添加回调事件

我们在Topbar中定义一个接口,名为TopbarClickListener,里面加入一个方法:onClickLButton()

public interface TopbarClickListener{
    public void onClickLButton();
}

然后,在Topbar中定义一个添加监听器的方法,将listener映射为Topbar中的listener。

private TopbarClickListener listener;

public void setTopbarClickListener(TopbarClickListener listener){
    this.listener = listener;
}

最后,只需要在构造方法中根据接口的函数做相应处理就好了,这里我们为按钮添加了点击事件,并在其中调用了接口的onClickButton方法。

leftButton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
        listener.onClickLButton();
    }
});

使用控件时,便可以这样使用:

Topbar topbar = (Topbar)findViewById(R.id.topbar);
topbar.setTopbarClickListener(new Topbar.TopbarClickListener() {
    @Override
    public void onClickLButton() {
        Toast.makeText(MainActivity.this,"成功点击返回按钮",Toast.LENGTH_SHORT).show();
    }
});

当我们点击返回按钮时,效果如下:

相关参考链接:点击此处

N0tExpectErr0r

N0tExpectErr0r

一名热爱代码的 Android 开发者

留下你的评论

*评论支持代码高亮<pre class="prettyprint linenums">代码</pre>