Carson帶你學(xué)Android:手把手教你寫一個(gè)完整的自定義View


前言

  • 自定義View是Android開(kāi)發(fā)者必須了解的基礎(chǔ)
  • 今天,我將手把手教你寫一個(gè)自定義View呀狼,并理清自定義View所有應(yīng)該的注意點(diǎn)

Carson帶你學(xué)Android自定義View文章系列:
Carson帶你學(xué)Android:自定義View基礎(chǔ)
Carson帶你學(xué)Android:一文梳理自定義View工作流程
Carson帶你學(xué)Android:自定義View繪制準(zhǔn)備-DecorView創(chuàng)建
Carson帶你學(xué)Android:自定義View Measure過(guò)程
Carson帶你學(xué)Android:自定義View Layout過(guò)程
Carson帶你學(xué)Android:自定義View Draw過(guò)程
Carson帶你學(xué)Android:手把手教你寫一個(gè)完整的自定義View
Carson帶你學(xué)Android:Canvas類全面解析
Carson帶你學(xué)Android:Path類全面解析


目錄

示意圖

1. 自定義View的分類

自定義View一共分為兩大類等曼,具體如下圖:

分類

2. 具體介紹 & 使用場(chǎng)景

對(duì)于自定義View的類型介紹及使用場(chǎng)景如下圖:

具體介紹 & 使用場(chǎng)景

3. 使用注意點(diǎn)

在使用自定義View時(shí)有很多注意點(diǎn)(坑)里烦,希望大家要非常留意:

使用注意點(diǎn)

3.1 支持特殊屬性

  • 支持wrap_content
    如果不在onMeasure()中對(duì)wrap_content作特殊處理,那么wrap_content屬性將失效

具體原因請(qǐng)看文章:為什么你的自定義View wrap_content不起作用禁谦?

  • 支持padding & margin
    如果不支持胁黑,那么paddingmargin(ViewGroup情況)的屬性將失效
  1. 對(duì)于繼承View的控件,padding是在draw()中處理
  2. 對(duì)于繼承ViewGroup的控件州泊,padding和margin會(huì)直接影響measure和layout過(guò)程

3.2 多線程應(yīng)直接使用post方式

View的內(nèi)部本身提供了post系列的方法别厘,完全可以替代Handler的作用,使用起來(lái)更加方便拥诡、直接触趴。

3.3 避免內(nèi)存泄露

主要針對(duì)View中含有線程或動(dòng)畫的情況:當(dāng)View退出或不可見(jiàn)時(shí),記得及時(shí)停止該View包含的線程和動(dòng)畫渴肉,否則會(huì)造成內(nèi)存泄露問(wèn)題冗懦。

啟動(dòng)或停止線程/ 動(dòng)畫的方式:

  1. 啟動(dòng)線程/ 動(dòng)畫:使用view.onAttachedToWindow(),因?yàn)樵摲椒ㄕ{(diào)用的時(shí)機(jī)是當(dāng)包含View的Activity啟動(dòng)的時(shí)刻
  2. 停止線程/ 動(dòng)畫:使用view.onDetachedFromWindow()仇祭,因?yàn)樵摲椒ㄕ{(diào)用的時(shí)機(jī)是當(dāng)包含View的Activity退出或當(dāng)前View被remove的時(shí)刻

3.4 處理好滑動(dòng)沖突

當(dāng)View帶有滑動(dòng)嵌套情況時(shí)披蕉,必須要處理好滑動(dòng)沖突,否則會(huì)嚴(yán)重影響View的顯示效果。


4. 具體實(shí)例

接下來(lái)没讲,我將用自定義View中最常用的繼承View來(lái)說(shuō)明自定義View的具體應(yīng)用和需要注意的點(diǎn)

4.1 繼承VIew的介紹

Paste_Image.png

在下面的例子中眯娱,我將講解:

  • 如何實(shí)現(xiàn)一個(gè)基本的自定義View(繼承VIew)
  • 如何自身支持wrap_content & padding屬性
  • 如何為自定義View提供自定義屬性(如顏色等等)
  • 實(shí)例說(shuō)明:畫一個(gè)實(shí)心圓

4.2 具體步驟

  1. 創(chuàng)建自定義View類(繼承View類)
  2. 布局文件添加自定義View組件及顯示
  3. 注意點(diǎn)設(shè)置(支持wrap_content & padding屬性自定義屬性等等)

下面我將逐個(gè)步驟進(jìn)行說(shuō)明:
步驟1:創(chuàng)建自定義View類(繼承View類)

/**
  * CircleView.java
  * 作用:繪制自定義View的具體內(nèi)容
  * 需復(fù)寫方法:onDraw()
  * 復(fù)寫邏輯:具體繪制邏輯
  */ 
  public class CircleView extends View {

      // 設(shè)置畫筆變量
      Paint mPaint1;

      // 自定義View有四個(gè)構(gòu)造函數(shù)
      // 如果View是在Java代碼里面new的,則調(diào)用第一個(gè)構(gòu)造函數(shù)
      public CircleView(Context context){
          super(context);

          // 在構(gòu)造函數(shù)里初始化畫筆的操作
          init();
      }


      // 如果View是在.xml里聲明的爬凑,則調(diào)用第二個(gè)構(gòu)造函數(shù)
      // 自定義屬性是從AttributeSet參數(shù)傳進(jìn)來(lái)的
      public CircleView(Context context,AttributeSet attrs){
          super(context, attrs);
          init();

      }

      // 不會(huì)自動(dòng)調(diào)用
      // 一般是在第二個(gè)構(gòu)造函數(shù)里主動(dòng)調(diào)用
      // 如View有style屬性時(shí)
      public CircleView(Context context,AttributeSet attrs,int defStyleAttr ){
          super(context, attrs,defStyleAttr);
          init();
      }


      // API21之后才使用
      // 不會(huì)自動(dòng)調(diào)用
      // 一般是在第二個(gè)構(gòu)造函數(shù)里主動(dòng)調(diào)用
      // 如View有style屬性時(shí)
      public  CircleView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
          super(context, attrs, defStyleAttr, defStyleRes);
      }

      // 畫筆初始化
      private void init() {

          // 創(chuàng)建畫筆
          mPaint1 = new Paint ();
          // 設(shè)置畫筆顏色為藍(lán)色
          mPaint1.setColor(Color.BLUE);
          // 設(shè)置畫筆寬度為10px
          mPaint1.setStrokeWidth(5f);
          //設(shè)置畫筆模式為填充
          mPaint1.setStyle(Paint.Style.FILL);

      }

      // 關(guān)鍵點(diǎn):復(fù)寫onDraw()進(jìn)行繪制  
      @Override
      protected void onDraw(Canvas canvas) {

          super.onDraw(canvas);

          // 獲取控件的高度和寬度
          int width = getWidth();
          int height = getHeight();

          // 設(shè)置圓的半徑 = 寬,高最小值的2分之1
          int r = Math.min(width, height)/2;

          // 畫出圓(藍(lán)色)
          // 圓心 = 控件的中央,半徑 = 寬,高最小值的2分之1
          canvas.drawCircle(width/2,height/2,r,mPaint1);
      }
  }

特別注意:

  1. View的構(gòu)造函數(shù)一共有4個(gè)徙缴,具體使用請(qǐng)看:深入理解View的構(gòu)造函數(shù)
    理解View的構(gòu)造函數(shù)
  2. 對(duì)于繪制內(nèi)容為何在復(fù)寫onDraw()里實(shí)現(xiàn),具體請(qǐng)看我寫的文章:自定義View Draw過(guò)程- 最易懂的自定義View原理系列(4)

步驟2:在布局文件中添加自定義View類的組件及顯示

/**
  * 1. 在布局文件中添加自定義View類的組件
  * activity_main.xml
  */ 
  <?xml version="1.0" encoding="utf-8"?>
  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="scut.carson_ho.diy_view.MainActivity">

    <!-- 注意添加自定義View組件的標(biāo)簽名:包名 + 自定義View類名-->
    <!--  控件背景設(shè)置為黑色-->
    <scut.carson_ho.diy_view.CircleView
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:background="#000000"
</RelativeLayout>


/**
  * 2. 設(shè)置顯示
  * MainActivity.java
  */ 
  public class MainActivity extends AppCompatActivity {

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

至此嘁信,一個(gè)基本的自定義View已經(jīng)實(shí)現(xiàn)了于样,運(yùn)行效果如下圖。

效果圖

步驟3:注意點(diǎn)設(shè)置(支持wrap_content & padding屬性自定義屬性等等)

接下來(lái)繼續(xù)看自定義View關(guān)于屬性自定義的問(wèn)題:

  • 如何手動(dòng)支持wrap_content屬性
  • 如何手動(dòng)支持padding屬性
  • 如何為自定義View提供自定義屬性(如顏色等等)

a. 手動(dòng)支持wrap_content屬性

先來(lái)看wrap_content & match_parent屬性的區(qū)別

// 視圖的寬和高被設(shè)定成剛好適應(yīng)視圖內(nèi)容的最小尺寸
android:layout_width="wrap_content"

// 視圖的寬和高延伸至充滿整個(gè)父布局
android:layout_width="match_parent"
// 在Android API 8之前叫作"fill_parent"

如果不手動(dòng)設(shè)置支持wrap_content屬性潘靖,那么wrap_content屬性是不會(huì)生效(顯示效果同match_parent

具體原因 & 解決方案請(qǐng)看我寫的文章:為什么你的自定義View wrap_content不起作用穿剖?

b. 支持padding屬性

padding屬性:用于設(shè)置控件內(nèi)容相對(duì)控件邊緣的邊距;

區(qū)別與margin屬性(同樣稱為:邊距):控件邊緣相對(duì)父控件的邊距(父控件控制)卦溢,具體區(qū)別如下:

Paste_Image.png

如果不手動(dòng)設(shè)置支持padding屬性糊余,那么padding屬性在自定義View中是不會(huì)生效的。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="scut.carson_ho.diy_view.MainActivity">

    <scut.carson_ho.diy_view.CircleView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        /**  添加Padding屬性单寂,但不會(huì)生效 **/
        android:padding="20dp"
         />
</RelativeLayout>

解決方案

繪制時(shí)考慮傳入的padding屬性值(四個(gè)方向)啄刹。

在自定義View類的復(fù)寫onDraw()進(jìn)行設(shè)置

/**
  * 復(fù)寫的onDraw()
  */ 
  @Override
  protected void onDraw(Canvas canvas) {

      super.onDraw(canvas);

      // 獲取傳入的padding值
      final int paddingLeft = getPaddingLeft();
      final int paddingRight = getPaddingRight();
      final int paddingTop = getPaddingTop();
      final int paddingBottom = getPaddingBottom();


      // 獲取繪制內(nèi)容的高度和寬度(考慮了四個(gè)方向的padding值)
      int width = getWidth() - paddingLeft - paddingRight ;
      int height = getHeight() - paddingTop - paddingBottom ;

      // 設(shè)置圓的半徑 = 寬,高最小值的2分之1
      int r = Math.min(width, height)/2;

      // 畫出圓(藍(lán)色)
      // 圓心 = 控件的中央,半徑 = 寬,高最小值的2分之1
      canvas.drawCircle(paddingLeft+width/2,paddingTop+height/2,r,mPaint1);

  }
效果圖

c. 提供自定義屬性

除了常見(jiàn)的以android:開(kāi)頭的系統(tǒng)屬性(如下所示),很多場(chǎng)景下自定義View還需要系統(tǒng)所沒(méi)有的屬性凄贩,即自定義屬性。

// 基本是以android開(kāi)頭
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:padding="30dp"

實(shí)現(xiàn)自定義屬性的步驟如下:

  1. 在values目錄下創(chuàng)建自定義屬性的xml文件
  2. 在自定義View的構(gòu)造方法中解析自定義屬性的值
  3. 在布局文件中使用自定義屬性

下面我將對(duì)每個(gè)步驟進(jìn)行具體介紹

步驟1:在values目錄下創(chuàng)建自定義屬性的xml文件

/**
  * attrs_circle_view.xml
  */ 
  <?xml version="1.0" encoding="utf-8"?>
  <resources>
      // 自定義屬性集合:CircleView
      // 在該集合下,設(shè)置不同的自定義屬性
      <declare-styleable name="CircleView">

          // 在attr標(biāo)簽下設(shè)置需要的自定義屬性
          // 此處定義了一個(gè)設(shè)置圖形的顏色:circle_color屬性,格式是color,代表顏色
          // 格式有很多種,如資源id(reference)等等
          <attr name="circle_color" format="color"/>

      </declare-styleable>
  </resources>

對(duì)于自定義屬性類型 & 格式如下:

<-- 1. reference:使用某一資源ID -->
<declare-styleable name="名稱">
    <attr name="background" format="reference" />
</declare-styleable>
// 使用格式
  // 1. Java代碼
  private int ResID;
  private Drawable ResDraw;
  ResID = typedArray.getResourceId(R.styleable.SuperEditText_background, R.drawable.background); // 獲得資源ID
  ResDraw = getResources().getDrawable(ResID); // 獲得Drawble對(duì)象

  // 2. xml代碼
<ImageView
    android:layout_width="42dip"
    android:layout_height="42dip"
    app:background="@drawable/圖片ID" />

<--  2. color:顏色值 -->
<declare-styleable name="名稱">
    <attr name="textColor" format="color" />
</declare-styleable>
// 格式使用
<TextView
    android:layout_width="42dip"
    android:layout_height="42dip"
    android:textColor="#00FF00" />

<-- 3. boolean:布爾值 -->
<declare-styleable name="名稱">
    <attr name="focusable" format="boolean" />
</declare-styleable>
// 格式使用
<Button
    android:layout_width="42dip"
    android:layout_height="42dip"
    android:focusable="true" />

<-- 4. dimension:尺寸值 -->
<declare-styleable name="名稱">
    <attr name="layout_width" format="dimension" />
</declare-styleable>
// 格式使用:
<Button
    android:layout_width="42dip"
    android:layout_height="42dip" />

<-- 5. float:浮點(diǎn)值 -->
<declare-styleable name="AlphaAnimation">
    <attr name="fromAlpha" format="float" />
    <attr name="toAlpha" format="float" />
</declare-styleable>
// 格式使用
<alpha
    android:fromAlpha="1.0"
    android:toAlpha="0.7" />

<-- 6. integer:整型值 -->
<declare-styleable name="AnimatedRotateDrawable">
    <attr name="frameDuration" format="integer" />
    <attr name="framesCount" format="integer" />
</declare-styleable>
// 格式使用
<animated-rotate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:frameDuration="100"
    android:framesCount="12"
 />

<-- 7. string:字符串 -->
<declare-styleable name="MapView">
    <attr name="apiKey" format="string" />
</declare-styleable>
// 格式使用
<com.google.android.maps.MapView
 android:apiKey="0jOkQ80oD1JL9C6HAja99uGXCRiS2CGjKO_bc_g" />

<-- 8. fraction:百分?jǐn)?shù) -->
<declare-styleable name="RotateDrawable">
    <attr name="pivotX" format="fraction" />
    <attr name="pivotY" format="fraction" />
</declare-styleable>
// 格式使用
<rotate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:pivotX="200%"
    android:pivotY="300%"
 />


<-- 9. enum:枚舉值 -->
<declare-styleable name="名稱">
    <attr name="orientation">
        <enum name="horizontal" value="0" />
        <enum name="vertical" value="1" />
    </attr>
</declare-styleable>
// 格式使用
<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
/>

<-- 10. flag:位或運(yùn)算 -->
<declare-styleable name="名稱">
    <attr name="windowSoftInputMode">
        <flag name="stateUnspecified" value="0" />
        <flag name="stateUnchanged" value="1" />
        <flag name="stateHidden" value="2" />
        <flag name="stateAlwaysHidden" value="3" />
        <flag name="stateVisible" value="4" />
        <flag name="stateAlwaysVisible" value="5" />
        <flag name="adjustUnspecified" value="0x00" />
        <flag name="adjustResize" value="0x10" />
        <flag name="adjustPan" value="0x20" />
        <flag name="adjustNothing" value="0x30" />
    </attr>
</declare-styleable>袱讹、
// 使用
<activity
    android:name=".StyleAndThemeActivity"
    android:label="@string/app_name"
    android:windowSoftInputMode="stateUnspecified | stateUnchanged | stateHidden" >

    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>



<-- 特別注意:屬性定義時(shí)可以指定多種類型值 -->
<declare-styleable name="名稱">
    <attr name="background" format="reference|color" />
</declare-styleable>
// 使用
<ImageView
    android:layout_width="42dip"
    android:layout_height="42dip"
    android:background="@drawable/圖片ID|#00FF00" />

步驟2:在自定義View的構(gòu)造方法中解析自定義屬性的值

/**
  * 此處是需要解析circle_color屬性的值
  * 該構(gòu)造函數(shù)需要重寫
  */ 
  public CircleView(Context context, AttributeSet attrs) {

        this(context, attrs,0);
        // 原來(lái)是:super(context,attrs);
        init();

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

          // 加載自定義屬性集合CircleView
          TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.CircleView);

          // 解析集合中的屬性circle_color屬性
          // 該屬性的id為:R.styleable.CircleView_circle_color
          // 將解析的屬性傳入到畫圓的畫筆顏色變量當(dāng)中(本質(zhì)上是自定義畫圓畫筆的顏色)
          // 第二個(gè)參數(shù)是默認(rèn)設(shè)置顏色(即無(wú)指定circle_color情況下使用)
          mColor = a.getColor(R.styleable.CircleView_circle_color,Color.RED);

          // 解析后釋放資源
          a.recycle();

          init();

 }

步驟3:在布局文件中使用自定義屬性

/**
  * activity_main.xml
  */ 
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  <!--必須添加schemas聲明才能使用自定義屬性-->
    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"
    tools:context="scut.carson_ho.diy_view.MainActivity"
    >
  
<!-- 注意添加自定義View組件的標(biāo)簽名:包名 + 自定義View類名-->
    <!--  控件背景設(shè)置為黑色-->
    <scut.carson_ho.diy_view.CircleView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:background="#000000"
        android:padding="30dp"

    <!--設(shè)置自定義顏色-->
        app:circle_color="#FF4081"
         />
</RelativeLayout>
Paste_Image.png

至此疲扎,一個(gè)較為規(guī)范的自定義View已經(jīng)完成了。

完整代碼下載

Carson_Ho的github:自定義View的具體應(yīng)用


5. 總結(jié)


歡迎關(guān)注Carson_Ho的簡(jiǎn)書

不定期分享關(guān)于安卓開(kāi)發(fā)的干貨捷雕,追求短椒丧、平、快救巷,但卻不缺深度壶熏。


請(qǐng)點(diǎn)贊!因?yàn)槟愕墓膭?lì)是我寫作的最大動(dòng)力浦译!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末棒假,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子精盅,更是在濱河造成了極大的恐慌帽哑,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叹俏,死亡現(xiàn)場(chǎng)離奇詭異妻枕,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門屡谐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)述么,“玉大人,你說(shuō)我怎么就攤上這事愕掏《让兀” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵亭珍,是天一觀的道長(zhǎng)敷钾。 經(jīng)常有香客問(wèn)我,道長(zhǎng)肄梨,這世上最難降的妖魔是什么阻荒? 我笑而不...
    開(kāi)封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮众羡,結(jié)果婚禮上侨赡,老公的妹妹穿的比我還像新娘。我一直安慰自己粱侣,他們只是感情好羊壹,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著齐婴,像睡著了一般油猫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上柠偶,一...
    開(kāi)封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天情妖,我揣著相機(jī)與錄音,去河邊找鬼诱担。 笑死毡证,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蔫仙。 我是一名探鬼主播料睛,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼摇邦!你這毒婦竟也來(lái)了恤煞?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤施籍,失蹤者是張志新(化名)和其女友劉穎阱州,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體法梯,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡苔货,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年犀概,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夜惭。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡姻灶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出诈茧,到底是詐尸還是另有隱情产喉,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布敢会,位于F島的核電站曾沈,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏鸥昏。R本人自食惡果不足惜塞俱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吏垮。 院中可真熱鬧障涯,春花似錦、人聲如沸膳汪。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)遗嗽。三九已至粘我,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間痹换,已是汗流浹背征字。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留晴音,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓缔杉,卻偏偏與公主長(zhǎng)得像锤躁,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子或详,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,498評(píng)論 25 707
  • 前言 自定義View是Android開(kāi)發(fā)中非常常用的知識(shí) 可是霸琴,在使用過(guò)程中椒振,有些開(kāi)發(fā)者會(huì)發(fā)現(xiàn):為什么自定義Vie...
    Carson帶你學(xué)安卓閱讀 33,352評(píng)論 24 114
  • 引言 本章內(nèi)容較多,先養(yǎng)養(yǎng)眼 大家知道梧乘,自定義View有三個(gè)重要的步驟:measure澎迎,layout庐杨,draw。而...
    SnowDragonYY閱讀 1,912評(píng)論 1 11
  • 我曾經(jīng)很希望未來(lái)某一天能跟你一起看春天的花夹供,夏天的雨灵份,秋天的葉,踏過(guò)冬天的雪哮洽。想要把這世界上最美好的東西全部拿到你...
    _Lethe_閱讀 239評(píng)論 0 0
  • 時(shí)常和我老爹也就是我爸爭(zhēng)辯填渠,關(guān)于誰(shuí)更懶的問(wèn)題。 我嫌棄他抽煙賭博不務(wù)正業(yè)鸟辅,他嫌棄我看劇游戲好吃懶做氛什,在彼此嫌棄的道...
    月非寒不寒閱讀 882評(píng)論 4 6