ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Android自定义TextView

2020-11-05 16:04:37  阅读:320  来源: 互联网

标签:MeasureSpec 自定义 int mPaint TextView Android MyTextView attrs


1.自定义属性

新建attrs.xml文件(res->values->attrs.xml),定义要自定义的TextView属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyTextView">

        <!--name 属性名称 format 格式-->
        <attr name="myText" format="string" />
        <attr name="myTextColor" format="color" />
        <attr name="myTextSize" format="dimension" />

    </declare-styleable>
</resources>

2.在布局中使用,对比系统TextView

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">


    <com.future.coding.custom_view.MyTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dp"
        app:myText="American Presidential Election"
        app:myTextColor="#D81B60"
        app:myTextSize="16sp" />


    <!--与上面自定义TextView的对比-->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="American Presidential Election"
        android:textColor="#D81B60"
        android:textSize="16sp" />

</LinearLayout>

3.通过继承View,实现自定义TextView

public class MyTextView extends View {

    private String mText;
    private int mTextSize = 16;
    private int mTextColor = Color.BLACK;

    private Paint mPaint;

    private static final String TAG = "MyTextView";

    //在代码中使用
    public MyTextView(Context context) {
        this(context, null);
    }

    //在布局layout中使用
    public MyTextView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    //在布局layout中使用,但会有style
    public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        //获取自定义属性
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyTextView);
        mText = typedArray.getString(R.styleable.MyTextView_myText);
        mTextColor = typedArray.getColor(R.styleable.MyTextView_myTextColor, mTextColor);

        Log.d(TAG, "MyTextView: " + sp2px(mTextSize));
        mTextSize = typedArray.getDimensionPixelSize(R.styleable.MyTextView_myTextSize, sp2px(mTextSize));


        /**
         * 解析:TypedArray 为什么需要调用recycle()
         * https://blog.csdn.net/Monicabg/article/details/45014327
         */
        typedArray.recycle();

        mPaint = new Paint();
        mPaint.setAntiAlias(true);//抗锯齿
        mPaint.setTextSize(mTextSize);
        mPaint.setColor(mTextColor);
    }


    private int sp2px(int sp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
                getResources().getDisplayMetrics());
    }

    /**
     * 自定义View的测量方法
     *
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        //指定控件的宽高,需要测量
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        if (widthMode == MeasureSpec.AT_MOST) {//在布局中指定了wrap_content

            Rect bounds = new Rect();
            mPaint.getTextBounds(mText, 0, mText.length(), bounds);
            widthSize = bounds.width() + getPaddingLeft() + getPaddingRight();
        } else if (widthMode == MeasureSpec.EXACTLY) {//在布局中指定了确定的值 比如:100dp / match_parent

        } else if (widthMode == MeasureSpec.UNSPECIFIED) {//尽可能的大,很少能用到
            //ListView、ScrollView在测量子布局的时候会用
        }


        if (heightMode == MeasureSpec.AT_MOST) {//在布局中指定了wrap_content

            Rect bounds = new Rect();
            mPaint.getTextBounds(mText, 0, mText.length(), bounds);
            heightSize = bounds.height() + getPaddingTop() + getPaddingBottom();
        } else if (heightMode == MeasureSpec.EXACTLY) {//在布局中指定了确定的值  比如:100dp / match_parent

        } else if (heightMode == MeasureSpec.UNSPECIFIED) {//尽可能的大,很少能用到
            //ListView、ScrollView在测量子布局的时候会用
        }

        setMeasuredDimension(widthSize, heightSize);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        /**
         * 自定义View之绘图篇(四):baseLine和FontMetrics
         * https://blog.csdn.net/u012551350/article/details/51361778
         */
        Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
        //中心线到基线的距离
        int dy = (int) ((fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom);
        //得到基线(BaseLine)
        int baseLine = getHeight() / 2 + dy;

        int x = getPaddingLeft();
        canvas.drawText(mText, x, baseLine, mPaint);
    }

}

 

--END

 

标签:MeasureSpec,自定义,int,mPaint,TextView,Android,MyTextView,attrs
来源: https://www.cnblogs.com/heibingtai/p/13932157.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有