Android群英传——第三章自定义View

自定义View

除了onMeasure() 测量、onLayout()布局、onDraw()绘制 这三个比较重要的View回调方法外,还有以下几个比较重要的回调方法:
onFinishInflate():从XML加载组件后调用
onSizeChanged():组件改变大小时调用
onTouchEvent():监听到触摸事件后回调
有三种自定义控件的方式:
继承类:对现有控件进行扩展,比如:继承TextView,重写onDraw()方法,实现新的功能。注意,如果要绘制需要使用getPaint()获取同一个画笔
组合类:通过几个控件组合成一个新的控件
重写类:继承View,自己绘制

继承控件:

给TextView家加上矩形边框

public class MyTextView extends TextView {

    private Paint mPaint;

    public MyTextView(Context context) {
        super(context);
    }

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

    public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        mPaint = getPaint();
        mPaint.setColor(Color.YELLOW);
        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);
        mPaint = new Paint();
        mPaint.setColor(Color.GREEN);
        canvas.drawRect(10, 10, getMeasuredWidth()-10, getMeasuredHeight()-10, mPaint);
        super.onDraw(canvas);
    }
}

以上需要明确几点:
- 使用canvas绘制时,先绘制的图像置于底层,后绘制的图像将会覆盖之前绘制的图像
- getPaint()可以获取系统在绘制这个组件时使用的画笔,如果你需要使用或者修改这个画笔的属性(如颜色等),可以使用getPaint()方法。也可以自定义一个Paint
- getMeasuredHeight()和getMeasureWidth()可以获取这个控件测量后的值,即调用onMeasure()后得到的控件大小

复合控件

TopBar:
先看效果:
这里写图片描述
上图是一个控件,由两个Button和一个TextView组成:

<resources>
    <!--定义属性-->
    <attr name="titleColor" format="color"/>
    <attr name="titleSize" format="dimension"/>
    <attr name="titleText" format="string"/>
    <attr name="leftTextColor" format="color"/>
    <attr name="leftTextSize" format="dimension"/>
    <attr name="leftText" format="string"/>
    <attr name="rightTextColor" format="color"/>
    <attr name="rightTextSize" format="dimension"/>
    <attr name="rightText" format="string"/>

    <!--给控件添加属性-->
    <declare-styleable name="TopBar">
        <attr name="titleColor"/>
        <attr name="titleSize"/>
        <attr name="titleText"/>
        <attr name="leftTextColor"/>
        <attr name="leftTextSize"/>
        <attr name="leftText"/>
        <attr name="rightTextColor"/>
        <attr name="rightTextSize"/>
        <attr name="rightText"/>
    </declare-styleable>
</resources>
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
 * Created by feathers on 16-11-13.
 */

public class TopBar extends LinearLayout {

    private int titleTextColor;
    private int leftTextColor;
    private int rightTextColor;
    private String titleText;
    private String rightText;
    private String leftText;
    private float titleTextSize;
    private float rightTextSize;
    private float leftTextSize;

    private Button leftButton;
    private Button rightButton;
    private TextView title;

    private TopbarClickListener topBarListener;

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

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

    public TopBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context, attrs);
    }

    private void initView(Context context, AttributeSet attrs) {
        // 取出TopBar拥有的所有属性
        TypedArray arrays = context.obtainStyledAttributes(attrs, R.styleable.TopBar);
        // 根据属性名指定属性值,参数二为如果使用者没有指定这个属性的值的默认值
        titleTextColor = arrays.getColor(R.styleable.TopBar_titleColor, Color.BLACK);
        leftTextColor = arrays.getColor(R.styleable.TopBar_leftTextColor, Color.BLACK);
        rightTextColor = arrays.getColor(R.styleable.TopBar_rightTextColor, Color.BLACK);
        titleText = arrays.getString(R.styleable.TopBar_titleText);
        rightText = arrays.getString(R.styleable.TopBar_rightText);
        leftText = arrays.getString(R.styleable.TopBar_leftText);
        titleTextSize = arrays.getDimension(R.styleable.TopBar_titleSize, 10);
        rightTextSize = arrays.getDimension(R.styleable.TopBar_rightTextSize, 10);
        leftTextSize = arrays.getDimension(R.styleable.TopBar_leftTextSize, 10);
        // 获取TypedArray后,调用recycle方法来避免重新创建的时候的错误
        arrays.recycle();

        // 将值设置到对应的组件中
        leftButton = new Button(context);
        rightButton = new Button(context);
        title = new TextView(context);
        leftButton.setTextColor(leftTextColor);
        leftButton.setText(leftText);
        leftButton.setTextSize(leftTextSize);
        title.setTextColor(titleTextColor);
        title.setText(titleText);
        title.setTextSize(titleTextSize);
        rightButton.setText(rightText);
        rightButton.setTextSize(rightTextSize);
        rightButton.setTextColor(rightTextColor);

        // 把定义好的控件添加到view group中
        LayoutParams params = new LayoutParams(context, attrs);
        params.gravity = Gravity.CENTER_VERTICAL; // 相当于linear layout layout_gravity属性
        this.setOrientation(HORIZONTAL);
        this.setLayoutParams(params);

        LayoutParams params1 = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
        params1.gravity = Gravity.CENTER; // 相当于linear layout gravity属性
        title.setGravity(Gravity.CENTER); // text view 的 gravity属性,让文字居中

        this.addView(leftButton, params1);
        this.addView(title, params1);
        this.addView(rightButton, params1);

        leftButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                topBarListener.onLeftClickListener();
            }
        });
        rightButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                topBarListener.onRightClickListener();
            }
        });
    }

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

    /**
     * Created by feathers on 16-11-13. 
     */
    public static interface TopbarClickListener { //提供接口

        void onLeftClickListener();

        void onRightClickListener();
    }
}

使用:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.feathers.demo.MainActivity">

    <com.example.feathers.demo.TopBar
        android:id="@+id/top_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:titleText="im Feathers"
        app:titleColor="#000000"
        app:titleSize="10dp"
        app:leftText="厉害"
        app:leftTextSize="10sp"
        app:rightText="牛X"
        app:rightTextSize="10sp">
    </com.example.feathers.demo.TopBar>

</RelativeLayout>
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TopBar topBar = (TopBar) findViewById(R.id.top_bar);
        topBar.setClickListener(new TopBar.TopbarClickListener() {
            @Override
            public void onLeftClickListener() {
                Toast.makeText(MainActivity.this, "left", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onRightClickListener() {
                Toast.makeText(MainActivity.this, "right", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

重写view绘制新的控件

需要熟练使用Canvas等类,要求较高

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值