自定義view - 自定義TextView

1. 思路分析


自定義View步驟:
1>:values__attrs.xml猛频,自定義屬性眼刃;
2>:在第三個(gè)構(gòu)造方法中獲取自定義屬性蒋院;
3>:onMeasure:不是非必須的哼勇;
4>:onDraw:所有繪制的代碼都寫(xiě)在onDraw方法中炸庞;

步驟分析:
1>:在values__attrs中定義自定義屬性;
2>:自定義MyTextView翠勉;
3>:在activity_mytextview布局文件中使用妖啥;

效果圖如下:
圖片.png
1>:values__attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!-- 自定義View的名字 -->
    <declare-styleable name="MyTextView">

        <!-- 以下是所用到的屬性-->

        <!-- 文字-string -->
        <attr name="novateText" format="string"/>
        <!-- 文字大小-dimension -->
        <attr name="novateTextSize" format="dimension"/>
        <!-- 文字長(zhǎng)度-->
        <attr name="novateMaxLength" format="integer"/>
        <!-- 文字顏色-color-->
        <attr name="novateColor" format="color"/>

        <!-- 枚舉 -->
        <attr name="novateInputType">
            <enum name="number" value="1"/>
            <enum name="text" value="2"/>
            <enum name="password" value="3"/>
        </attr>

    </declare-styleable>
</resources>
2>:MyTextView
/**
 * ================================================
 * Email: 2185134304@qq.com
 * Created by Novate 2018/12/28 10:52
 * Version 1.0
 * Params:
 * Description:    自定義TextView
 * ================================================
*/

public class MyTextView extends View {

    // 文字
    private String mText ;
    // 文字默認(rèn)大小 15sp
    private int mTextSize = 15 ;
    // 文字默認(rèn)顏色
    private int mTextColor = Color.BLACK ;
    // 初始化畫(huà)筆
    private Paint mPaint ;

    /**
     * 這種調(diào)用第1個(gè)構(gòu)造方法
     * TextView tv = new TextView(this):
     */
    public MyTextView(Context context) {
        this(context,null);
    }

    /**
     * 這種調(diào)用第2個(gè)構(gòu)造方法
     * <com.novate.test.customview.MyTextView
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             app:novateText="北京Novate"
             app:novateTextSize="20sp"
             app:novateColor="#ff0000"
             android:background="#00FF00"
             />
     */
    public MyTextView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    /**
     * 這個(gè)和第二個(gè)方法一樣,只是該布局文件中含有 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_novateText) ;
        // 獲取文字大小
        mTextSize = typedArray.getDimensionPixelSize(R.styleable.MyTextView_novateTextSize , sp2px(mTextSize)) ;
        // 獲取文字顏色
        typedArray.getColor(R.styleable.MyTextView_novateColor , mTextColor) ;
        // 釋放資源
        typedArray.recycle();

        // 創(chuàng)建畫(huà)筆
        mPaint = new Paint() ;
        // 設(shè)置抗鋸齒对碌,讓文字比較清晰荆虱,同時(shí)文字也會(huì)變得圓滑
        mPaint.setAntiAlias(true);
        // 設(shè)置文字大小
        mPaint.setTextSize(mTextSize);
        // 設(shè)置畫(huà)筆顏色
        mPaint.setColor(mTextColor);
    }


    /**
     * 測(cè)量文字
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // TODO:方式1:如果在布局文件中設(shè)置的寬高都是固定值[比如100dp、200dp等],就用下邊方式直接獲取寬高
        int width = MeasureSpec.getSize(widthMeasureSpec) ;
        int height = MeasureSpec.getSize(heightMeasureSpec) ;



        //  TODO:方式2:如果調(diào)用者在布局文件給自定義MyTextView的寬高屬性設(shè)置wrap_content怀读,
        // 就需要通過(guò)下邊的 widthMode和heightMode來(lái)獲取寬高
        // 獲取寬高模式
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        // 如果在布局中設(shè)置寬高都是wrap_content[對(duì)應(yīng)AT_MOST]诉位,必須用mode計(jì)算
        if (widthMode == MeasureSpec.AT_MOST){
            // 文字寬度 與字體大小和長(zhǎng)度有關(guān)
            Rect rect = new Rect() ;
            // 獲取文本區(qū)域 param1__測(cè)量的文字 param2__從位置0開(kāi)始 param3__到文字長(zhǎng)度
            mPaint.getTextBounds(mText , 0 , mText.length() , rect);
            // 文字寬度 getPaddingLeft寬度 getPaddingRight高度 寫(xiě)這兩個(gè)原因是為了在布局文件中設(shè)置padding屬性起作用
            width = rect.width() + getPaddingLeft() + getPaddingRight() ;
        }

        if (heightMode == MeasureSpec.AT_MOST){
            Rect rect = new Rect() ;
            mPaint.getTextBounds(mText , 0 , mText.length() , rect);
            height = rect.height() + getPaddingTop() + getPaddingBottom() ;
        }

        // 給文字設(shè)置寬高
        setMeasuredDimension(width , height);
    }


    /**
     * 繪制文字
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint.FontMetricsInt fontMetricsInt = mPaint.getFontMetricsInt();
        int dy = (fontMetricsInt.bottom - fontMetricsInt.top)/2 - fontMetricsInt.bottom ;
        int baseLine = getHeight()/2 + dy ;
        int x = getPaddingLeft() ;
        canvas.drawText(mText , x , baseLine , mPaint);
    }

    /**
     *  sp轉(zhuǎn)為px
     */
    private int sp2px(int sp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
                getResources().getDisplayMetrics());
    }
}
3>:activity_mytextview
<?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"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.novate.test.customview.MyTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:novateText="北京Novate"
        app:novateTextSize="20sp"
        app:novateColor="#ff0000"
        android:background="#00FF00"
        />
</LinearLayout>
4>:MyTextViewActivity
public class MyTextViewActivity extends AppCompatActivity {
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mytextview);
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市菜枷,隨后出現(xiàn)的幾起案子苍糠,更是在濱河造成了極大的恐慌,老刑警劉巖犁跪,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件椿息,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡坷衍,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)条舔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)枫耳,“玉大人,你說(shuō)我怎么就攤上這事孟抗∏ㄑ睿” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵凄硼,是天一觀的道長(zhǎng)铅协。 經(jīng)常有香客問(wèn)我,道長(zhǎng)摊沉,這世上最難降的妖魔是什么狐史? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮说墨,結(jié)果婚禮上骏全,老公的妹妹穿的比我還像新娘。我一直安慰自己尼斧,他們只是感情好姜贡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著棺棵,像睡著了一般楼咳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上烛恤,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天母怜,我揣著相機(jī)與錄音,去河邊找鬼棒动。 笑死糙申,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播柜裸,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼缕陕,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了疙挺?” 一聲冷哼從身側(cè)響起扛邑,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎铐然,沒(méi)想到半個(gè)月后蔬崩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡搀暑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年沥阳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片自点。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡桐罕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出桂敛,到底是詐尸還是另有隱情功炮,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布术唬,位于F島的核電站薪伏,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏粗仓。R本人自食惡果不足惜嫁怀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望潦牛。 院中可真熱鬧眶掌,春花似錦、人聲如沸巴碗。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)橡淆。三九已至召噩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間逸爵,已是汗流浹背具滴。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留师倔,地道東北人构韵。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親疲恢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子凶朗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 【Android 自定義View】 [TOC] 自定義View基礎(chǔ) 接觸到一個(gè)類(lèi),你不太了解他显拳,如果貿(mào)然翻閱源碼只...
    Rtia閱讀 3,948評(píng)論 1 14
  • 轉(zhuǎn)自:http://www.reibang.com/p/e9d8420b1b9c 自定義View是Android...
    CQ_TYL閱讀 1,837評(píng)論 0 26
  • 原文地址:http://www.android100.org/html/201606/06/241682.html...
    AFinalStone閱讀 923評(píng)論 0 1
  • 本文整理自: Google 官方文檔之自定義 View棚愤,筆者省略了對(duì)自己幫助不大的章節(jié),拜讀原文請(qǐng)點(diǎn)鏈接杂数。 一宛畦、繼...
    程序員K哥閱讀 415評(píng)論 0 3
  • 常用的篩選工具次和,居然還有這么多神奇的使用,通過(guò)這3節(jié)課里那伐,我只能說(shuō)Excel只有你想不到的斯够,沒(méi)有它做不到的! 1喧锦、...
    碧曌_7066閱讀 571評(píng)論 3 1