20170831工作日记--自定义View学习

Posted buder

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20170831工作日记--自定义View学习相关的知识,希望对你有一定的参考价值。

  学习了LayoutInflater的原理分析、视图的绘制流程、视图的状态及重绘等知识,按类型来划分的话,自定义View的实现方式大概可以分为三种,自绘控件、组合控件、以及继承控件。那么下面我们就来依次学习一下,每种方式分别是如何自定义View的。

(一)自绘控件

  自绘控件的意思就是,这个View上所展现的内容全部都是我们自己绘制出来的。绘制的代码是写在onDraw()方法中的。参考相关博客 http://blog.csdn.net/guolin_blog/article/details/17357967

  下面我们准备来自定义一个计数器View,这个View可以响应用户的点击事件,并自动记录一共点击了多少次。新建一个CounterView继承自View,代码如下所示:

 

 1 /**
 2  * Created by nubia on 2017/8/31.
 3  */
 4 
 5 public class CounterView extends View implements View.OnClickListener {
 6 
 7     private Paint mPaint;
 8     private Rect mBounds;
 9     private int mCount;
10 
11     public CounterView(Context context, @Nullable AttributeSet attrs) {
12         super(context, attrs);
13         mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
14         mBounds = new Rect();
15         setOnClickListener(this);
16     }
17 
18     @Override
19     protected void onDraw(Canvas canvas) {
20         super.onDraw(canvas);
21         /**
22          * 蓝色画笔,画出来个矩形
23          */
24         mPaint.setColor(Color.BLUE);
25         canvas.drawRect(0,0,getWidth(),getHeight(),mPaint);
26 
27         /**
28          * 画笔变成黄色,绘制文字
29          */
30         mPaint.setColor(Color.YELLOW);
31         mPaint.setTextSize(30);
32         String text = String.valueOf(mCount);
33         mPaint.getTextBounds(text,0,text.length(),mBounds);
34         float textWidth = mBounds.width();
35         float textHeight = mBounds.height();
36         canvas.drawText(text,getWidth()/2-textWidth/2,getHeight()/2+textHeight/2,mPaint);;
37     }
38 
39     /**
40      * 调用invalidate()方法会导致视图进行重绘,因此onDraw()方法在稍后就将会得到调用
41      * @param view
42      */
43     @Override
44     public void onClick(View view) {
45         mCount++;
46         invalidate();
47     }
48 }

 

 

  可以看到,首先我们在CounterView的构造函数中初始化了一些数据,并给这个View的本身注册了点击事件,这样当CounterView被点击的时候,onClick()方法就会得到调用。而onClick()方法中的逻辑就更加简单了,只是对mCount这个计数器加1,然后调用invalidate()方法。通过 Android视图状态及重绘流程分析,带你一步步深入了解View(三) 这篇文章的学习我们都已经知道,调用invalidate()方法会导致视图进行重绘,因此onDraw()方法在稍后就将会得到调用。

   既然CounterView是一个自绘视图,那么最主要的逻辑当然就是写在onDraw()方法里的了,下面我们就来仔细看一下。这里首先是将Paint画笔设置为蓝色,然后调用Canvas的drawRect()方法绘制了一个矩形,这个矩形也就可以当作是CounterView的背景图吧。接着将画笔设置为黄色,准备在背景上面绘制当前的计数,注意这里先是调用了getTextBounds()方法来获取到文字的宽度和高度,然后调用了drawText()方法去进行绘制就可以了。

  这样,一个自定义的View就已经完成了,并且目前这个CounterView是具备自动计数功能的。那么剩下的问题就是如何让这个View在界面上显示出来了,其实这也非常简单,我们只需要像使用普通的控件一样来使用CounterView就可以了。比如在布局文件中加入如下代码:

 

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="match_parent"
 3     android:layout_height="match_parent" >
 4 
 5     <com.example.myview.CounterView
 6         android:layout_width="100dp"
 7         android:layout_height="100dp"
 8         android:layout_centerInParent="true" />
 9 
10 </RelativeLayout>

 

 

 

  可以看到,这里我们将CounterView放入了一个RelativeLayout中,然后可以像使用普通控件来给CounterView指定各种属性,比如通过layout_width和layout_height来指定CounterView的宽高,通过android:layout_centerInParent来指定它在布局里居中显示。只不过需要注意,自定义的View在使用的时候一定要写出完整的包名,不然系统将无法找到这个View。

 

 (二)组合控件

 

  组合控件的意思就是,我们并不需要自己去绘制视图上显示的内容,而只是用系统原生的控件就好了,但我们可以将几个系统原生的控件组合到一起,这样创建出的控件就被称为组合控件。

 

  举个例子来说,标题栏就是个很常见的组合控件,很多界面的头部都会放置一个标题栏,标题栏上会有个返回按钮和标题,点击按钮后就可以返回到上一个界面。那么下面我们就来尝试去实现这样一个标题栏控件。

 

建一个title.xml布局文件,代码如下所示:

 

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="50dp"
 5     android:background="#9999cc">
 6 
 7     <Button
 8         android:id="@+id/button_left"
 9         android:layout_width="80dp"
10         android:layout_height="60dp"
11         android:layout_centerVertical="true"
12         android:layout_marginLeft="2dp"
13         android:background="@mipmap/aaa" />
14 
15     <TextView
16         android:id="@+id/title_text"
17         android:layout_width="wrap_content"
18         android:layout_height="wrap_content"
19         android:layout_centerInParent="true"
20         android:text="this is Title"
21         android:textColor="#fff"
22         android:textSize="30sp"
23         android:textStyle="bold" />
24 
25 
26 </RelativeLayout>

 

 接下来创建一个TitleView继承自FrameLayout,代码如下所示: 

/**
 * Created by nubia on 2017/8/31.
 */

public class TitleView extends FrameLayout {

    private Button leftButton;
    private TextView titleText;

    public TitleView(final Context context, AttributeSet attrs) {
        super(context, attrs);
        LayoutInflater.from(context).inflate(R.layout.title, this);
        titleText = findViewById(R.id.title_text);
        leftButton = findViewById(R.id.button_left);
        leftButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //((Activity)getContext()).finish();
                TextView t = findViewById(R.id.title_text);
                t.setText("sha bi ");
            }
        });
    }
}

 

   TitleView中的代码非常简单,在TitleView的构建方法中,我们调用了LayoutInflater的inflate()方法来加载刚刚定义的title.xml布局,这部分内容我们已经在 Android LayoutInflater原理分析,带你一步步深入了解View(一) 这篇文章中学习过了。

   到了这里,一个自定义的标题栏就完成了,那么下面又到了如何引用这个自定义View的部分,其实方法基本都是相同的,在布局文件中添加如下代码:

 

1 <com.example.myview.TitleView
2         android:id="@+id/title_view"
3         android:layout_width="match_parent"
4         android:layout_height="wrap_content" />

 (三)继承控件

还没看明白 http://blog.csdn.net/guolin_blog/article/details/17357967

 

以上是关于20170831工作日记--自定义View学习的主要内容,如果未能解决你的问题,请参考以下文章

cathome 猫家 开发日记-自定义控件

Android学习笔记View的工作原理

Flutter学习日记之自定义封装Dialog

学习日记0827异常处理 元类 自定义元类 自定义元类来实例化类 属性查找顺序

Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习

自定义View学习笔记-1