Android群英传-自定义View、控件

来源:互联网 发布:程序员直播赚钱 编辑:程序博客网 时间:2024/05/17 04:07

注意点

  1. 绘制View的显示内容,需要重写onDraw()方法
  2. 该View若要使用wrap_content属性,必须重写onMeasure()方法
  3. 通过自定义attrs属性,还可以设置新的属性配置值

View中重要的回调方法

  1. ++onFinishInflate()++: 从XML加载组件后回调
  2. ++onSizeChanged()++:组件大小改变时
  3. onMeasure():进行测量
  4. onLayout(): 确定显示的位置
  5. onTouchEvent(): 监听触摸事件时回调

自定义控件三大方法

一、现有控件进行扩展

比如扩展TextView
思路如下:

    @Override    protected void onDraw(Canvas canvas) {        //回调父类方法前,实现自己的逻辑,对TextView来说在“绘制文本”内容之前        super.onDraw(canvas);        //回调父类方法后,实现自己的逻辑,对TextView来说在“绘制文本”内容之后    }

1.利用画笔绘制矩形框

public class MyTextView extends TextView {    public MyTextView(Context context) {        super(context);    }    public MyTextView(Context context,AttributeSet attrs) {        super(context, attrs);    }    @Override    protected void onDraw(Canvas canvas) {        //回调父类方法前,实现自己的逻辑,对TextView来说在“绘制文本”内容之前        Paint mPaint1 = new Paint();        mPaint1.setColor(ContextCompat.getColor(getContext(), R.color.colorAccent));        mPaint1.setStyle(Paint.Style.FILL);        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint1);        canvas.save();        //绘制文字前平移10像素(px)        canvas.translate(10, 0);        super.onDraw(canvas);        canvas.restore();    }}

2.LinearGradient ShaderMatrix实现动态的文字闪动效果

需要onDraw()onSizeChanged()

    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if(mMatrix != null){            mTranslate += mViewWidth/5;            if(mTranslate > 2*mViewWidth){                mTranslate = -mViewWidth;            }            mMatrix.setTranslate(mTranslate, 0);            mLinearGradient.setLocalMatrix(mMatrix);            postInvalidateDelayed(100);        }    }@Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        if(mViewWidth == 0){            mViewWidth = getMeasuredWidth();            if(mViewWidth > 0){                mPaint = getPaint();                mLinearGradient = new LinearGradient(                        0,                        0,                        mViewWidth,                        0,                        new int[]{                                Color.BLUE, 0xffffffff,                                Color.BLUE},                        null,                        Shader.TileMode.CLAMP);                mPaint.setShader(mLinearGradient);                mMatrix = new Matrix();            }        }    }

二、复合控件

简单的组合控件:
链接:http://blog.csdn.net/yelangjueqi/article/details/8879340

1.定义属性

为一个View提供自定义的属性,只需要在resvalues目录下创建一个attrs.xml的属性定义文件,代码参考下面:

使用UI模板需要引用第三方控件的名字空间
* 下列引用android的系统属性

xmlns:android="http://schemas.android.com/apk/res/android"
  • 第三方的控件都使用如下代码来引用名字空间
xmlns:app="http://schemas.android.com/apk/res-auto"

android studio需要使用xmlns:app

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="TopBar">        <attr name="Title" format="string"/>        <attr name="TitleTextSize" format="dimension"/>        <attr name="TitleTextColor" format="color"/>        <attr name="RightText" format="string"/>        <attr name="RightTextSize" format="dimension"/>        <attr name="RightTextColor" format="color"/>        <attr name="LeftImageSize" format="integer"/>    </declare-styleable></resources>

2.自定义控件类

package com.example.lenovo.qqdemos.CustomView;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Color;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.View;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView;import com.example.lenovo.qqdemos.R;/** * Created by feather on 2016/8/19. */public class TopBar extends LinearLayout{    private ImageView mHeadImage;    private TextView mTitleText;    private TextView mRightText;    //标题    String mTitle;    int mTitleTextColor;    float mTitleTextSize;    //左侧头像    float mHeadImageSize;    //右侧文本    String mRightTextStr;    int mRightTextColor;    float mRightTextSize;    //接口    topbarClickListener mListener;    public TopBar(Context context, AttributeSet attrs) {        super(context, attrs);        //注意参数: root=this, 及 attachToRo        LayoutInflater.from(context).inflate(R.layout.feather_topbar, this, true);        mHeadImage = (ImageView) findViewById(R.id.topbar_head_image);        mTitleText = (TextView) findViewById(R.id.topbar_title);        mRightText = (TextView) findViewById(R.id.topbar_right_text);        //将在 atts.xml中定义的 declare-styleable的所有属性的值存储到 TypedArray中        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TopBar);        /*-----------------------------------------------------------         *   标题-根据属性初始化         * ----------------------------------------------------------*/        String mTitle = typedArray.getString(R.styleable.TopBar_Title);        int mTitleTextColor = typedArray.getColor(R.styleable.TopBar_TitleTextColor, Color.WHITE);        float mTitleTextSize = typedArray.getDimension(R.styleable.TopBar_TitleTextSize, 20);        if(mTitle != null) mTitleText.setText(mTitle);        mTitleText.setTextColor(mTitleTextColor);        mTitleText.setTextSize(mTitleTextSize);        /*-----------------------------------------------------------         *   左侧头像-根据属性初始化         * ----------------------------------------------------------*/        int mHeadImageSize = typedArray.getInt(R.styleable.TopBar_LeftImageSize, 20);        mHeadImage.setMaxWidth(mHeadImageSize);        mHeadImage.setMaxHeight(mHeadImageSize);        //监听器        mHeadImage.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                mListener.leftImageClick();            }        });        /*-----------------------------------------------------------         *   右侧文本-根据属性初始化         * ----------------------------------------------------------*/        String mRightTextStr = typedArray.getString(R.styleable.TopBar_RightText);        int mRightTextColor = typedArray.getColor(R.styleable.TopBar_RightTextColor, Color.WHITE);        float mRightTextSize = typedArray.getDimension(R.styleable.TopBar_RightTextSize, 20);        if(mRightTextStr != null) mRightText.setText(mRightTextStr);        mRightText.setTextColor(mRightTextColor);        mRightText.setTextSize(mRightTextSize);        //监听器        mRightText.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                mListener.rightTextClick();            }        });    }    public interface topbarClickListener{        void leftImageClick();        void rightTextClick();    }}
1.其中使用属性的办法
        //将在 atts.xml中定义的 declare-styleable的所有属性的值存储到 TypedArray中        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TopBar);        /*-----------------------------------------------------------         *   根据属性初始化         * ----------------------------------------------------------*/        String mTitle = typedArray.getString(R.styleable.TopBar_Title);        int mTitleTextColor = typedArray.getColor(R.styleable.TopBar_TitleTextColor, Color.WHITE);        float mTitleTextSize = typedArray.getDimension(R.styleable.TopBar_TitleTextSize, 20);        int mHeadImageSize = typedArray.getInt(R.styleable.TopBar_LeftImageSize, 20);        String mRightTextStr = typedArray.getString(R.styleable.TopBar_RightText);        int mRightTextColor = typedArray.getColor(R.styleable.TopBar_RightTextColor, Color.WHITE);        float mRightTextSize = typedArray.getDimension(R.styleable.TopBar_RightTextSize, 20);        //避免重新创建时的错误        typedArray.recycle();
2.该控件的布局
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="@color/colorBlue"    android:orientation="vertical" >    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:background="#00000000">        <com.pkmmte.view.CircularImageView            android:id="@+id/topbar_head_image"            android:layout_width="40dp"            android:layout_height="40dp"            android:src="@drawable/default_user_head"            android:layout_alignParentLeft="true"            android:layout_centerVertical="true"            android:visibility="invisible"            >        </com.pkmmte.view.CircularImageView>        <TextView            android:id="@+id/topbar_title"            android:layout_width="wrap_content"            android:layout_height="match_parent"            android:text="标题"            android:textSize="20dp"            android:gravity="center"            android:textColor="@color/white"            android:layout_centerInParent="true"            android:visibility="invisible"/>        <TextView            android:id="@+id/topbar_right_text"            android:layout_width="wrap_content"            android:layout_height="match_parent"            android:layout_centerInParent="true"            android:text="编辑"            android:textSize="20dp"            android:layout_alignParentRight="true"            android:layout_marginRight="4dp"            android:textColor="@color/white"            android:gravity="center"            android:visibility="invisible"/>    </RelativeLayout></LinearLayout>

3.使用该控件

  • 可以通过xmlns:app="http://schemas.android.com/apk/res-auto"使用自定义属性,如下面app:Title部分
    <com.example.lenovo.qqdemos.CustomView.TopBar        xmlns:app="http://schemas.android.com/apk/res-auto"        android:id="@+id/chat_menu_topbar"        android:layout_width="match_parent"        android:layout_height="55dp"        app:Title="hello">    </com.example.lenovo.qqdemos.CustomView.TopBar>

错误提示

1.android.view.InflateException: Binary XML file line #9: Error inflating class com.feather.past.MyTextView

2.java.lang.NoSuchMethodException: [class android.content.Context, interface android.util.AttributeSet]

1.报错原因:

在自定义view时,没有重写含有(Context context,AttributeSet attrs)的构造器

解决办法:

重新对于构造器,例如:

 public ControlKeyboardLinearLayout(Context context,AttributeSet attrs){         super(context, attrs);     }

2.报错原因:

自定义view为内部类时,没有将内部类设置为static,例如:

public class a{   public class b extents TextVIew{           ...   }}
解决办法:

为内部类加上static关键字,例如:

public class a{    public static class b extents TextVIew{       ...    }}
0 0
原创粉丝点击