1.简述
简而言之,即 如继承TextView,修改默认background、marquee状态时,elevation值、取消默认最小高度等。
2.前提基础
了解View的生命周期,关联Activity联动时的函数调用顺序
- 【View】构造方法
- 【View】onFinishInflate()
- 【Activity】 onCreate()
- 【Activity】onStart()
- 【Activity】onResume()
- 【View】onAttachedToWindow()
- 【View】onMeasure() (可能调用n次)
- 【View】onSizeChanged() (可能调用n次)
- 【View】onLayout() (可能调用n次)
- 【View】onDraw() (可能调用n次)
- 【View】onWindowFocusChanged() (调用Activity.onPause()前,被调用,hasWindowFocus==false)
- 【Activity】onPause()
- 【Activity】onStop()
- 【Activity】onDestroy()
- 【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用就好了,"
/>