從自定義輸入框了解自定義View的基礎(chǔ)

在App市場(chǎng)中蔗牡,我們經(jīng)秤毕担可以看到許多的非常炫的頁(yè)面,他們?cè)O(shè)計(jì)精美注重細(xì)節(jié)蛋逾,用戶體驗(yàn)非常好集晚。而這種頁(yè)面的開(kāi)發(fā),通常Android自帶的原生控件是無(wú)法滿足的区匣,所以就需要我們根據(jù)不同的需求進(jìn)行自定義View偷拔。而根據(jù)設(shè)計(jì)和功能需求不同,我們通常有三種方法來(lái)實(shí)現(xiàn)自定義View:

  1. 組合:將不同控件組合在一起形成新的控件亏钩;
  2. 擴(kuò)展:在現(xiàn)有控件的基礎(chǔ)上莲绰,進(jìn)行擴(kuò)展;
  3. 重寫(xiě):現(xiàn)有控件無(wú)法滿足姑丑,通過(guò)重寫(xiě)來(lái)實(shí)現(xiàn)全新的控件蛤签;

本文以常見(jiàn)的自定義文本輸入框?yàn)槔樱窒韺?shí)現(xiàn)方式以及相關(guān)的自定義控件知識(shí)點(diǎn)栅哀。

需求 - 復(fù)雜自定義輸入框

整個(gè)控件包含三部分:標(biāo)題欄震肮,輸入框,提示信息欄留拾。要求該輸入框上面包含一個(gè)文本控件顯示標(biāo)題戳晌,下面包含一個(gè)文本控件顯示提示信息,合起來(lái)是一個(gè)完整的控件痴柔,并有多個(gè)新添加屬性沦偎,能夠?yàn)橛脩籼峁ML配置方式,也可以Java代碼配置。如圖所示輸入框豪嚎,能夠?qū)Σ煌瑺顟B(tài)有不同的顯示:

  1. 正常狀態(tài)下搔驼,灰色邊框,且為圓角矩形侈询;


    正常狀態(tài)下
  2. 得到焦點(diǎn)時(shí)舌涨,藍(lán)色邊框,且為圓角矩形妄荔;


    得到焦點(diǎn)時(shí)
  3. 校驗(yàn)輸入內(nèi)容泼菌,發(fā)現(xiàn)有錯(cuò)誤時(shí),紅色邊框啦租,圓角矩形,且有感嘆號(hào)提示圖標(biāo)用來(lái)提醒用戶荒揣;


    發(fā)生錯(cuò)誤時(shí)

分析

  1. 輸入框:該輸入框包含多個(gè)狀態(tài)篷角,但分析可知,類似Android原生的EditText控件系任,且該控件現(xiàn)有功能無(wú)法滿足多種狀態(tài)的要求恳蹲,因?yàn)椋梢?strong>擴(kuò)展EditText俩滥,在原生控件的基礎(chǔ)上進(jìn)行擴(kuò)展嘉蕾,增加功能,修改UI顯示效果霜旧;
  2. 整體:包含三部分:標(biāo)題 + 輸入框 + 提示信息错忱,即TextView + 擴(kuò)展EditText + TextView,且要作為一個(gè)整體提供給用戶使用挂据,姑且將此控件成為CustomInputView以清。即幾個(gè)基本控件組合在一起行成新的控件,這種方式通常需要繼承一個(gè)合適的ViewGroup崎逃,然后添加指定功能控件掷倔,形成新的控件,且可以指定可配置屬性个绍,增強(qiáng)可配置性勒葱;

一、自定義View實(shí)現(xiàn)構(gòu)造函數(shù)

(一) 實(shí)現(xiàn):繼承View并自定義輸入框的構(gòu)造函數(shù)

保證自定義view不管通過(guò)哪種方式創(chuàng)建都可以走到相應(yīng)的邏輯

public CustomView(Context context) {
     this(context, null); 
}

public CustomView(Context context, @Nullable AttributeSet attrs) {
     this(context, attrs, 0);
}

public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
     super(context, attrs, defStyleAttr);
     //do something
}

通過(guò)繼承View或者合適的布局(比如這里實(shí)現(xiàn)自定義輸入框巴柿,可以直接繼承EditText凛虽;或者考慮到包含三部分標(biāo)題+控件+提示信息,可以直接繼承線性布局LinearLayout)篮洁,并實(shí)現(xiàn)View的構(gòu)造函數(shù)涩维,之后就可以對(duì)其進(jìn)行改造,實(shí)現(xiàn)我們想要的自定義效果。但是其中有四個(gè)構(gòu)造函數(shù)瓦阐,他們分別什么意義呢蜗侈?我們這里又為什么只實(shí)現(xiàn)了三個(gè)呢?

(二) 原理:四個(gè)構(gòu)造函數(shù)

  1. 用Java代碼創(chuàng)建View睡蟋,如果只用這個(gè)構(gòu)造函數(shù)聲明踏幻,該View沒(méi)有任何參數(shù),基本是個(gè)空View對(duì)象戳杀;
public View(Context context)
  1. 從XML中創(chuàng)建View该面,且參數(shù)attr是在XML中配置的參數(shù);
public View(Context context, AttributeSet attrs)
  1. 從XML中創(chuàng)建View信卡,且有自定義屬性時(shí)調(diào)用隔缀。系統(tǒng)默認(rèn)只會(huì)調(diào)用前兩個(gè)構(gòu)造函數(shù),至于第三個(gè)構(gòu)造函數(shù)的調(diào)用,通常是在構(gòu)造函數(shù)中主動(dòng)調(diào)用的(例如,在第二個(gè)構(gòu)造函數(shù)中調(diào)用第三個(gè)構(gòu)造函數(shù));
public View(Context context,  AttributeSet attrs, int defStyleAttr)
  1. 從XML中創(chuàng)建View傍菇,且有自定義屬性猾瘸,且需要在SDK21以上才能使用;
public View(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)

知道了不同的構(gòu)造函數(shù)的含義后丢习,那么我們自定義View時(shí)牵触,應(yīng)該重寫(xiě)哪個(gè)構(gòu)造函數(shù)呢?首先我們要區(qū)分不同構(gòu)造函數(shù)的調(diào)用時(shí)機(jī)咐低,一共四個(gè)構(gòu)造函數(shù)揽思,第一個(gè)是Java代碼創(chuàng)建時(shí)調(diào)用;后三個(gè)都是XML創(chuàng)建见擦,其中第二個(gè)比較好理解钉汗,即attr參數(shù)就是XML中配置的參數(shù);那么后兩個(gè)構(gòu)造函數(shù)又有什么區(qū)別呢锡宋?他們都是與主題相關(guān)儡湾,從而使得一些View即使不對(duì)其進(jìn)行任何配置,也有一些默認(rèn)屬性执俩,所以徐钠,在自定義View時(shí),如果不需要View隨著主題變化而變化役首,有前兩個(gè)構(gòu)造函數(shù)就夠了尝丐。

(三) 原理:View的屬性和主題

不同View的形態(tài)不同,是因?yàn)槠渑渲玫膶傩圆煌獍拢赩iew中有很多屬性爹袁,如color,background等矮固,這些屬性可以在不同位置進(jìn)行配置:(1)可以直接寫(xiě)在XML文件中失息;(2)可以在XML中以style形式定義譬淳;(3)theme主題中定義;(4)defStyleAttr盹兢;(5)defStyleRes邻梆;且他們的優(yōu)先級(jí)為:
XML直接定義 > XML中style引用 > defStyleAttr > defStyleRes > theme直接定義

  1. defStyleAttr:只要在主題中對(duì)這個(gè)屬性賦值,該View就會(huì)自動(dòng)應(yīng)用這個(gè)屬性的值绎秒。在給這個(gè)屬性賦值時(shí)浦妄,在xml中一般使用@style/xxx形式;
  2. defStyleRes:只有在第三個(gè)參數(shù)defStyleAttr為0见芹,或者主題中沒(méi)有找到這個(gè)defStyleAttr屬性的賦值時(shí)剂娄,才可以啟用。而且這個(gè)參數(shù)不再是Attr了玄呛,而是真正的style阅懦。其實(shí)這也是一種低級(jí)別的“默認(rèn)主題”,即在主題未聲明屬性值時(shí)把鉴,我們可以主動(dòng)的給一個(gè)style故黑,使用這個(gè)構(gòu)造函數(shù)定義出的View,其主題就是這個(gè)定義的defStyleRes庭砍。

具體關(guān)于優(yōu)先級(jí)驗(yàn)證的例子見(jiàn)這篇博客

二、自定義屬性

(一) 實(shí)現(xiàn)步驟1:編寫(xiě)styleable和item等標(biāo)簽元素

通過(guò)declare-styleable標(biāo)簽為其配置自定義屬性混埠,在res/values/attrs.xml文件中編寫(xiě)styleable和item等標(biāo)簽元素:

<resources>
    <declare-styleable name="CustomView">
        <attr name="custom_attr1" format="string" />
        <attr name="custom_attr2" format="boolean" />
        <attr name="custom_attr3" format="integer" />
        <attr name="custom_attr4" format="dimension" />
    </declare-styleable>
    <attr name="custom_attr5" format="string" />
</resources>

聲明了一個(gè)自定義屬性集MyCustomView,其中包含了custom_attr1,custom_att2,custom_attr3,custom_attr4四個(gè)屬性.同時(shí),我們還聲明了一個(gè)獨(dú)立的屬性custom_attr5怠缸;

(二) 實(shí)現(xiàn)步驟2:在XML布局文件中使用

  1. 在根布局引用命名空間
xmlns:app="http://schemas.android.com/apk/res-auto"
  1. 在布局文件中使用自定義view
  <com.example.myapplication.CustomView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:custom_attr1="test"
        app:custom_attr2="true"
        app:custom_attr3="1"
        app:custom_attr4="1dp"
        app:custom_attr5="base"/>

(三) 實(shí)現(xiàn)步驟3:在CustomView的構(gòu)造方法中通過(guò)TypedArray獲取

TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
String testStr = ta.getString(R.styleable.CustomView_custom_attr1);
boolean testBool = ta.getBoolean(R.styleable.CustomView_custom_attr2, false);
ta.recycle();

通過(guò)以上四個(gè)步驟,我們就為自定義view定義了自定義屬性钳宪,且可以通過(guò)XML進(jìn)行配置揭北,并讀取到配置的屬性值,并對(duì)其進(jìn)行操作吏颖。下面是其中的一些原理:

(四) 原理:AttributeSet與TypedArray

  1. AttributeSet:包含該View聲明的所有的屬性的集合搔体。可以通過(guò)getAttributeName()方法獲取所有屬性的key半醉,getAttributeValue()方法獲取所有屬性的value疚俱;例如:
<com.example.myapplication.CustomView
    android:layout_width="100dp"
    android:layout_height="100dp"
    app:custom_attr1="test"/>

解析出來(lái)的key和value值為:

attrName = layout_width , attrVal = 100.0dip
attrName = layout_height , attrVal = 200.0dip
attrName = text , attrVal = test
  1. TypedArray:簡(jiǎn)化解析屬性的工作。如果布局中的屬性的值是引用類型(比如:@dimen/dp100)缩多,AttributeSet解析出來(lái)的結(jié)果是@數(shù)字的字符串呆奕,即id。如果使用AttributeSet去獲得最終的字符串衬吆,那么需要第一步拿到id梁钾,第二步再去解析id。而TypedArray正是幫我們簡(jiǎn)化了這個(gè)過(guò)程逊抡。例如:
<com.example.myapplication.CustomView
    android:layout_width="@dimen/dp100"
    android:layout_height="100dp"
    app:custom_attr1="@string/test"/>

解析出來(lái)的key和value值為:

attrName = layout_width , attrVal = @2130065234
attrName = layout_height , attrVal = 100.0dip
attrName = text , attrVal = @2131211809

如果用AttributeSet解析像素值姆泻,代碼為:

int widthDimenId = attrs.getAttributeResourceValue(0, -1);
int width = getResources().getDimension(widthDimenId);

結(jié)論:在View的構(gòu)造方法中,可以通過(guò)AttributeSet去獲得自定義屬性的值,但是比較麻煩拇勃,而TypedArray可以很方便的獲取四苇。

(五) 原理:declare-styleable

  1. styleale的出現(xiàn)系統(tǒng)可以為我們完成很多常量(int[]數(shù)組,下標(biāo)常量)等的編寫(xiě)潜秋,簡(jiǎn)化開(kāi)發(fā)工作蛔琅;
  2. attr中的屬性不可以重復(fù)定義,可以一次定義峻呛,多次使用罗售。可以聲明一個(gè)parent钩述,父類style寨躁,其他style繼承該父類使用,其中定義和使用的區(qū)別:
    (1)定義:<attr name="testAttr" format="integer" />
    (2)使用:<attr name="testAttr"/>

結(jié)論:Android會(huì)根據(jù)其在R.java中生成一些常量方便我們使用(aapt干的)牙勘,本質(zhì)上职恳,可以不聲明declare-styleable,僅僅聲明所需的屬性即可方面,但是比較麻煩放钦,而declare-styleable可以使我們方便的獲取。

具體關(guān)于自定義屬性驗(yàn)證的例子見(jiàn)這篇博客

三恭金、設(shè)置不同樣式對(duì)應(yīng)不同狀態(tài)

(一) 實(shí)現(xiàn):一個(gè)文件實(shí)現(xiàn)不同狀態(tài)的樣式

  1. 第一種方式:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!--可編輯狀態(tài)操禀,失焦時(shí):灰色-->
    <item android:state_enabled="true" android:state_focused="false">
            <shape android:shape="rectangle">
                   <stroke android:width="@dimen/dp1" android:color="@color/grey">
            </shape>
    </item>
    <!--可編輯狀態(tài),且獲得焦點(diǎn)時(shí):藍(lán)色-->
    <item android:state_enabled="true" android:state_focused="true">
            <shape android:shape="rectangle">
                   <stroke android:width="@dimen/dp1" android:color="@color/blue">
            </shape>
    </item>
</selector>
  1. 第二種方式:
    或者也可以將其中不同狀態(tài)對(duì)應(yīng)的item抽成一個(gè)文件横腿,以防如果其他控件使用可以直接調(diào)用颓屑,代碼如下:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!--可編輯狀態(tài),失焦時(shí):灰色-->
    <item android:drawable="@drawable/custom_drawable1" android:state_enabled="true" android:state_focused="false" />
    <!--可編輯狀態(tài)耿焊,且獲得焦點(diǎn)時(shí):藍(lán)色-->
    <item android:drawable="@drawable/custom_drawable2" android:state_enabled="true" android:state_focused="true" />
</selector>

其中揪惦,custom_drawable1.xml的代碼為:(custom_drawable2類似)

<shape android:shape="rectangle">
      <stroke android:width="@dimen/dp1" android:color="@color/grey">
</shape>

(二) 原理:selector選擇器

定義資源文件xml時(shí),使用selector標(biāo)簽罗侯,可以添加一個(gè)或多個(gè)item子標(biāo)簽器腋,而相應(yīng)的狀態(tài)是在item標(biāo)簽中定義的。定義的xml文件可以作為兩種資源使用:drawable和color:

  1. 作為drawable資源使用時(shí)歇父,一般和shape一樣放于drawable目錄下蒂培,item必須指定android:drawable屬性;使用的例子見(jiàn)上面代碼((一) 實(shí)現(xiàn):一個(gè)文件實(shí)現(xiàn)不同狀態(tài)的樣式)
  2. 作為color資源使用時(shí)榜苫,則放于color目錄下护戳,item必須指定android:color屬性;使用例子見(jiàn)下面:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 當(dāng)前窗口失去焦點(diǎn)時(shí) -->
    <item android:color="@android:color/black" android:state_window_focused="false" />
    <!-- 不可用時(shí) -->
    <item android:color="@android:color/background_light" android:state_enabled="false" />
    <!-- 按壓時(shí) -->
    <item android:color="@android:color/holo_blue_light" android:state_pressed="true" />
    <!-- 被選中時(shí) -->
    <item android:color="@android:color/holo_green_dark" android:state_selected="true" />
    <!-- 被激活時(shí) -->
    <item android:color="@android:color/holo_green_light" android:state_activated="true" />
    <!-- 默認(rèn)時(shí) -->
    <item android:color="@android:color/white" />
</selector>

其中垂睬,注意:

  1. android:drawable屬性除了引用@drawable資源媳荒,也可以引用@color顏色值抗悍;但android:color只能引用@color;
  2. item是從上往下匹配的钳枕,如果匹配到一個(gè)item那它就將采用這個(gè)item缴渊,而不是采用最佳匹配的規(guī)則;所以設(shè)置默認(rèn)的狀態(tài)鱼炒,一定要寫(xiě)在最后衔沼,如果寫(xiě)在前面,則后面所有的item都不會(huì)起作用昔瞧;

總結(jié)

根據(jù)以上介紹指蚁,可以簡(jiǎn)單寫(xiě)出一個(gè)標(biāo)題+輸入框+提示信息的布局了,且可以自定義屬性值自晰,主要代碼如下:

public class CustomView extends LinearLayout {

    private TextView title;
    private TextView description;
    private EditText input;

    //custom property
    private String customAttr1;
    private Boolean customAttr2;

    public CustomView(Context context) {
        this(context, null);
    }

    public CustomView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        initViews(context);
        initProperties(context, attrs);
    }

    private void initViews(Context context) {
        setOrientation(VERTICAL);
        title = new TextView(context);
        addView(title);
        
        input = new EditText(context);
        input.setBackgroundResource(R.drawable.custom_input_selector);
        input.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {        
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }

            @Override
            public void afterTextChanged(Editable s) {
                if(somethingWrong()) {
                    input.setBackgroundResource(R.drawable.custom_input_error);
                } else {
                    input.setBackgroundResource(R.drawable.custom_input_selector);
                }
                //或者可以使用三目運(yùn)算符
                //input.setBackgroundResource(somethingWrong()? R.drawable.custom_input_error : R.drawable.custom_input_selector);
            }
        });
        addView(input);
        
        description = new EditText(context);
        addView(description);
    }

    private void initProperties(Context context, @Nullable AttributeSet attrs) {
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
        setCustomAttr1(ta.getString(R.styleable.CustomView_custom_attr1));
        setCustomAttr2(ta.getBoolean(R.styleable.CustomView_custom_attr2, false));
        ta.recycle();
    }

    public void setCustomAttr1(String attr) {
        customAttr1 = attr;
    }

    public void setCustomAttr2(boolean attr) {
        customAttr2 = attr;
    }

    public String getCustomAttr1() {
        return customAttr1;
    }

    public Boolean getCustomAttr2() {
        return customAttr2;
    }
}

實(shí)用的常用Tips

  1. 給ImageView設(shè)置水波紋效果:
android:background="?android:attr/selectableItemBackground"
  1. 可以利用ContextThemeWrapper引入style來(lái)修改控件樣式凝化,能夠方便的將自定義樣式寫(xiě)入style,減少代碼酬荞,如:
ContextThemeWrapper wrapper = new ContextThemeWrapper(context, R.style.CustomStyle);
CustomView customView = new CustomView(wrapper);

但要注意搓劫,慎用這種方式,ContextThemeWrapper會(huì)改變當(dāng)前theme混巧,并改變此后再使用的context枪向,有可能會(huì)影響較大。

  1. 設(shè)置當(dāng)前自定義控件的寬度和高度
customView.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.WRAP_CONTENT);
//或者
customView.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.WRAP_CONTENT));
  1. 調(diào)用UI線程延遲執(zhí)行
new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
       //doSomething
    }
},100);  //延遲100毫秒執(zhí)行

參考文獻(xiàn)

Android View 四個(gè)構(gòu)造函數(shù)詳解
Android 深入理解Android中的自定義屬性

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載咧党,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者遣疯。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市凿傅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌数苫,老刑警劉巖聪舒,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異虐急,居然都是意外死亡箱残,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)止吁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)被辑,“玉大人,你說(shuō)我怎么就攤上這事敬惦∨卫恚” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵俄删,是天一觀的道長(zhǎng)宏怔。 經(jīng)常有香客問(wèn)我奏路,道長(zhǎng),這世上最難降的妖魔是什么臊诊? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任鸽粉,我火速辦了婚禮,結(jié)果婚禮上抓艳,老公的妹妹穿的比我還像新娘触机。我一直安慰自己,他們只是感情好玷或,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布儡首。 她就那樣靜靜地躺著,像睡著了一般庐椒。 火紅的嫁衣襯著肌膚如雪椒舵。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天约谈,我揣著相機(jī)與錄音笔宿,去河邊找鬼。 笑死棱诱,一個(gè)胖子當(dāng)著我的面吹牛泼橘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播迈勋,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼炬灭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了靡菇?” 一聲冷哼從身側(cè)響起重归,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎厦凤,沒(méi)想到半個(gè)月后鼻吮,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡较鼓,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年椎木,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片博烂。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡香椎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出禽篱,到底是詐尸還是另有隱情畜伐,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布谆级,位于F島的核電站烤礁,受9級(jí)特大地震影響讼积,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜脚仔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一勤众、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鲤脏,春花似錦们颜、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至硫嘶,卻和暖如春阻问,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背沦疾。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工称近, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人哮塞。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓刨秆,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親忆畅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子衡未,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

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