008-Android自定义View(3):衍生(扩展式)详解(图文)

221 阅读2分钟

1.简述

简而言之,即 如继承TextView,修改默认background、marquee状态时,elevation值、取消默认最小高度等。

2.前提基础

了解View的生命周期,关联Activity联动时的函数调用顺序

  1. 【View】构造方法
  2. 【View】onFinishInflate()
  3. 【Activity】 onCreate()
  4. 【Activity】onStart()
  5. 【Activity】onResume()
  6. 【View】onAttachedToWindow()
  7. 【View】onMeasure() (可能调用n次)
  8. 【View】onSizeChanged() (可能调用n次)
  9. 【View】onLayout() (可能调用n次)
  10. 【View】onDraw() (可能调用n次)
  11. 【View】onWindowFocusChanged() (调用Activity.onPause()前,被调用,hasWindowFocus==false)
  12. 【Activity】onPause()
  13. 【Activity】onStop()
  14. 【Activity】onDestroy()
  15. 【View】onDetachedFromWindow

可参考 : Android自定义View(1):基础


细节注意:

运行时,动态更新View的两种方法区别 1.invalidate():

简单重绘View:如更新其文本、颜色、状态等。只调用onDraw()方法。

2.requestLayout():

可约等于视为完全重绘整个View,因为该方法调用后,会从onMeasure()开始更新View

3. 实践

改写内容见代码备注

3.1 自定义View类

package com.cupster.base_super_resource;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.TextView;

import androidx.annotation.Nullable;

public class AlwaysMarqueeTextView extends TextView {
    public AlwaysMarqueeTextView(Context context) {
        super(context);
        initExTool(context , null);
    }

    public AlwaysMarqueeTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initExTool(context ,attrs);
    }

    public AlwaysMarqueeTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initExTool(context ,attrs);
    }

    public AlwaysMarqueeTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        initExTool(context ,attrs);
    }

    //========================================================================
    //============================   扩展1   =================================
    //========================================================================
    //重置父类判断跑马灯滚动条件1
    @Override
    public boolean isFocused() {
        return true;
    }
    //重置父类判断跑马灯滚动条件2
    @Override
    public void setSelected(boolean selected) {
        super.setSelected(true);
    }

    //========================================================================
    //============================   扩展2   =================================
    //========================================================================

    private Paint mPaint;
    private int underColor = -1;

    private void  initExTool(Context context ,AttributeSet attrs){
        mPaint = new Paint();
        if (attrs == null){
            mPaint.setColor(Color.BLUE);
        }else {
            TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AlwaysMarqueeTextView);
            //取值
             underColor= typedArray.getInt(R.styleable.AlwaysMarqueeTextView_under_color, Color.parseColor("#0000ff"));
            //使用
            mPaint.setColor(underColor);
            //释放
            typedArray.recycle();
        }
        //----------------------
        //------- 扩展3 ---------
        //----------------------
        initSetting();
    }
    @Override
    protected void onDraw(Canvas canvas) {
        //添加下划线
        super.onDraw(canvas);
        mPaint.setColor(Color.GREEN);
        canvas.drawLine( 0 ,getHeight()/2 ,getWidth() ,getHeight()/2 , mPaint);
    }
    //========================================================================
    //============================   扩展3   =================================
    //========================================================================
    private void initSetting() {
        setEllipsize(TextUtils.TruncateAt.MARQUEE);//跑马灯滚动
        setMarqueeRepeatLimit(-1);//-1无限循环,1循环一次 ,n 循环n次
        setSingleLine(true);
        setHorizontallyScrolling(true);
        setFocusable(true);
        setFocusableInTouchMode(true);
    }
}

3.2 自定义属性

res/values/attrs.xml

    <declare-styleable name="AlwaysMarqueeTextView">
        <attr name="under_color" format="color" />
    </declare-styleable>

3.3 布局文件中使用

<!--  <你的包名.AlwaysMarqueeTextView -->
        <com.cupster.base_super_resource.AlwaysMarqueeTextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:under_color="@android:color/holo_green_dark"
            android:text="这是一个跑马灯跑啊跑,滚啊滚,循环次数为无限次,textview扩展/改写效果,总之当成事textview用就好了,"
            />