跟著郭大俠一步步深入了解View第四篇之Android自定義View的實(shí)現(xiàn)方法

作者:guolin
來(lái)源:CSDN
原文:https://blog.csdn.net/guolin_blog/article/details/12921889
版權(quán)聲明:本文為博主原創(chuàng)文章蒲凶,轉(zhuǎn)載請(qǐng)附上博文鏈接吧秕!


不知不覺(jué)中官觅,帶你一步步深入了解View系列的文章已經(jīng)寫到第四篇了,回顧一下掠河,我們一共學(xué)習(xí)了LayoutInflater的原理分析、視圖的繪制流程、視圖的狀態(tài)及重繪等知識(shí),算是把View中很多重要的知識(shí)點(diǎn)都涉及到了芒率。

今天這篇文章講一講自定義View的實(shí)現(xiàn)方法,同時(shí)這也是帶你一步步深入了解View系列的完結(jié)篇篙顺。

如果說(shuō)要按類型來(lái)劃分的話偶芍,自定義View的實(shí)現(xiàn)方式大概可以分為三種,自繪控件德玫、組合控件匪蟀、以及繼承控件。那么下面我們就來(lái)依次學(xué)習(xí)一下宰僧,每種方式分別是如何自定義View的材彪。

1. 自繪控件

自繪控件的意思就是,這個(gè)View上所展現(xiàn)的內(nèi)容全部都是我們自己繪制出來(lái)的琴儿。繪制的代碼是寫在onDraw()方法中的

下面我們準(zhǔn)備來(lái)自定義一個(gè)計(jì)數(shù)器View查刻,這個(gè)View可以響應(yīng)用戶的點(diǎn)擊事件,并自動(dòng)記錄一共點(diǎn)擊了多少次凤类。新建一個(gè)CounterView繼承自View穗泵,代碼如下所示:

public class CounterView extends View implements View.OnClickListener {

    private Paint mPaint;
    private Rect mBounds;
    private int mCount;

    public CounterView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBounds = new Rect();
        setOnClickListener(this);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(Color.BLUE);
        canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);
        mPaint.setColor(Color.YELLOW);
        mPaint.setTextSize(30);
        String text = String.valueOf(mCount);
        mPaint.getTextBounds(text, 0, text.length(), mBounds);
        float textWidth = mBounds.width();
        float textHeight = mBounds.height();
        canvas.drawText(text, getWidth() / 2 - textWidth / 2, getHeight() / 2 + textHeight / 2, mPaint);
    }

    @Override
    public void onClick(View v) {
        mCount++;
        invalidate();
    }
}

可以看到,首先我們?cè)贑ounterView的構(gòu)造函數(shù)中初始化了一些數(shù)據(jù)谜疤,并給這個(gè)View的本身注冊(cè)了點(diǎn)擊事件佃延,這樣當(dāng)CounterView被點(diǎn)擊的時(shí)候,onClick()方法就會(huì)得到調(diào)用夷磕。而onClick()方法中的邏輯就更加簡(jiǎn)單了履肃,只是對(duì)mCount這個(gè)計(jì)數(shù)器加1,然后調(diào)用invalidate()方法坐桩。通過(guò)深入了解View第三篇之Android視圖狀態(tài)及重繪流程分析這篇文章的學(xué)習(xí)我們都已經(jīng)知道尺棋,調(diào)用invalidate()方法會(huì)導(dǎo)致視圖進(jìn)行重繪,因此onDraw()方法在稍后就將會(huì)得到調(diào)用绵跷。

既然CounterView是一個(gè)自繪視圖膘螟,那么最主要的邏輯當(dāng)然就是寫在onDraw()方法里的了成福,下面我們就來(lái)仔細(xì)看一下。這里首先是將Paint畫筆設(shè)置為藍(lán)色荆残,然后調(diào)用Canvas的drawRect()方法繪制了一個(gè)矩形奴艾,這個(gè)矩形也就可以當(dāng)作是CounterView的背景圖吧。接著將畫筆設(shè)置為黃色内斯,準(zhǔn)備在背景上面繪制當(dāng)前的計(jì)數(shù)蕴潦,注意這里先是調(diào)用了getTextBounds()方法來(lái)獲取到文字的寬度和高度,然后調(diào)用了drawText()方法去進(jìn)行繪制就可以了俘闯。

這樣潭苞,一個(gè)自定義的View就已經(jīng)完成了,并且目前這個(gè)CounterView是具備自動(dòng)計(jì)數(shù)功能的真朗。那么剩下的問(wèn)題就是如何讓這個(gè)View在界面上顯示出來(lái)了此疹,其實(shí)這也非常簡(jiǎn)單,我們只需要像使用普通的控件一樣來(lái)使用CounterView就可以了蜜猾。比如在布局文件中加入如下代碼:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.example.diyview.CounterView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_centerInParent="true" />

</RelativeLayout>

可以看到秀菱,這里我們將CounterView放入了一個(gè)RelativeLayout中,然后可以像使用普通控件來(lái)給CounterView指定各種屬性蹭睡,比如通過(guò)layout_width和layout_height來(lái)指定CounterView的寬高衍菱,通過(guò)android:layout_centerInParent來(lái)指定它在布局里居中顯示。只不過(guò)需要注意肩豁,自定義的View在使用的時(shí)候一定要寫出完整的包名脊串,不然系統(tǒng)將無(wú)法找到這個(gè)View。

好了清钥,就是這么簡(jiǎn)單琼锋,接下來(lái)我們可以運(yùn)行一下程序,并不停地點(diǎn)擊CounterView祟昭,效果如下圖所示缕坎。

20190521_145649.gif

怎么樣?是不是感覺(jué)自定義View也并不是什么高級(jí)的技術(shù)篡悟,簡(jiǎn)單幾行代碼就可以實(shí)現(xiàn)了谜叹。當(dāng)然了,這個(gè)CounterView功能非常簡(jiǎn)陋搬葬,只有一個(gè)計(jì)數(shù)功能荷腊,因此只需幾行代碼就足夠了,當(dāng)你需要繪制比較復(fù)雜的View時(shí)急凰,還是需要很多技巧的女仰。

2. 組合控件

組合控件的意思就是,我們并不需要自己去繪制視圖上顯示的內(nèi)容,而只是用系統(tǒng)原生的控件就好了疾忍,但我們可以將幾個(gè)系統(tǒng)原生的控件組合到一起乔外,這樣創(chuàng)建出的控件就被稱為組合控件。

舉個(gè)例子來(lái)說(shuō)锭碳,標(biāo)題欄就是個(gè)很常見(jiàn)的組合控件袁稽,很多界面的頭部都會(huì)放置一個(gè)標(biāo)題欄勿璃,標(biāo)題欄上會(huì)有個(gè)返回按鈕和標(biāo)題擒抛,點(diǎn)擊按鈕后就可以返回到上一個(gè)界面。那么下面我們就來(lái)嘗試去實(shí)現(xiàn)這樣一個(gè)標(biāo)題欄控件补疑。

新建一個(gè)title.xml布局文件歧沪,代碼如下所示:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:background="#ffcb05" >

    <Button
        android:id="@+id/button_left"
        android:layout_width="60dp"
        android:layout_height="40dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="5dp"
        android:text="Back"
        android:textColor="#fff" />

    <TextView
        android:id="@+id/title_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="This is Title"
        android:textColor="#fff"
        android:textSize="20sp" />

</RelativeLayout>

在這個(gè)布局文件中,我們首先定義了一個(gè)RelativeLayout作為背景布局莲组,然后在這個(gè)布局里定義了一個(gè)Button和一個(gè)TextView诊胞,Button就是標(biāo)題欄中的返回按鈕,TextView就是標(biāo)題欄中的顯示的文字锹杈。

接下來(lái)創(chuàng)建一個(gè)TitleView繼承自FrameLayout撵孤,代碼如下所示:

public class TitleView extends FrameLayout{
    private Button leftButton;

    private TextView titleText;

    public TitleView(Context context, AttributeSet attrs) {
        super(context, attrs);
        LayoutInflater.from(context).inflate(R.layout.title, this);
        titleText = (TextView) findViewById(R.id.title_text);
        leftButton = (Button) findViewById(R.id.button_left);
        leftButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ((Activity) getContext()).finish();
            }
        });
    }

    public void setTitleText(String text) {
        titleText.setText(text);
    }

    public void setLeftButtonText(String text) {
        leftButton.setText(text);
    }

    public void setLeftButtonListener(View.OnClickListener l) {
        leftButton.setOnClickListener(l);
    }
}

TitleView中的代碼非常簡(jiǎn)單,在TitleView的構(gòu)建方法中竭望,我們調(diào)用了LayoutInflater的inflate()方法來(lái)加載剛剛定義的title.xml布局邪码,這部分內(nèi)容我們已經(jīng)在深入了解View第一篇之Android LayoutInflater原理分析這篇文章中學(xué)習(xí)過(guò)了。

接下來(lái)調(diào)用findViewById()方法獲取到了返回按鈕的實(shí)例咬清,然后在它的onClick事件中調(diào)用finish()方法來(lái)關(guān)閉當(dāng)前的Activity闭专,也就相當(dāng)于實(shí)現(xiàn)返回功能了。

另外旧烧,為了讓TitleView有更強(qiáng)地?cái)U(kuò)展性影钉,我們還提供了setTitleText()、setLeftButtonText()掘剪、setLeftButtonListener()等方法平委,分別用于設(shè)置標(biāo)題欄上的文字、返回按鈕上的文字夺谁、以及返回按鈕的點(diǎn)擊事件廉赔。

到了這里,一個(gè)自定義的標(biāo)題欄就完成了予权,那么下面又到了如何引用這個(gè)自定義View的部分昂勉,其實(shí)方法基本都是相同的,在布局文件中添加如下代碼:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.example.diyview.TitleView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/title_view">
    </com.example.diyview.TitleView>

</RelativeLayout>

這樣就成功將一個(gè)標(biāo)題欄控件引入到布局文件中了扫腺,運(yùn)行一下程序岗照,效果如下圖所示:


Screenshot_2019-05-21-15-30-59-283_com.example.di.png

現(xiàn)在點(diǎn)擊一下Back按鈕,就可以關(guān)閉當(dāng)前的Activity了。如果你想要修改標(biāo)題欄上顯示的內(nèi)容攒至,或者返回按鈕的默認(rèn)事件厚者,只需要在Activity中通過(guò)findViewById()方法得到TitleView的實(shí)例,然后調(diào)用setTitleText()迫吐、setLeftButtonText()库菲、setLeftButtonListener()等方法進(jìn)行設(shè)置就OK了。

3. 繼承控件

繼承控件的意思就是志膀,我們并不需要自己重頭去實(shí)現(xiàn)一個(gè)控件熙宇,只需要去繼承一個(gè)現(xiàn)有的控件,然后在這個(gè)控件上增加一些新的功能溉浙,就可以形成一個(gè)自定義的控件了烫止。這種自定義控件的特點(diǎn)就是不僅能夠按照我們的需求加入相應(yīng)的功能,還可以保留原生控件的所有功能戳稽,比如 Android PowerImageView實(shí)現(xiàn)馆蠕,可以播放動(dòng)畫的強(qiáng)大ImageView 這篇文章中介紹的PowerImageView就是一個(gè)典型的繼承控件。

為了能夠加深大家對(duì)這種自定義View方式的理解惊奇,下面我們?cè)賮?lái)編寫一個(gè)新的繼承控件互躬。ListView相信每一個(gè)Android程序員都一定使用過(guò),這次我們準(zhǔn)備對(duì)ListView進(jìn)行擴(kuò)展颂郎,加入在ListView上滑動(dòng)就可以顯示出一個(gè)刪除按鈕吼渡,點(diǎn)擊按鈕就會(huì)刪除相應(yīng)數(shù)據(jù)的功能。

首先需要準(zhǔn)備一個(gè)刪除按鈕的布局祖秒,新建delete_button.xml文件诞吱,代碼如下所示:

<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/delete_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="delete">
</Button>

這個(gè)布局文件很簡(jiǎn)單,只有一個(gè)按鈕而已竭缝。

接著創(chuàng)建MyListView繼承自ListView房维,這就是我們自定義的View了,代碼如下所示:

public class MyListView extends ListView implements View.OnTouchListener, GestureDetector.OnGestureListener {

    private GestureDetector gestureDetector;
    private OnDeleteListener listener;
    private View deleteButton;
    private ViewGroup itemLayout;
    private int selectedItem;
    private boolean isDeleteShown;

    public MyListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        gestureDetector = new GestureDetector(getContext(), this);
        setOnTouchListener(this);
    }

    public void setOnDeleteListener(OnDeleteListener l) {
        listener = l;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (isDeleteShown) {
            itemLayout.removeView(deleteButton);
            deleteButton = null;
            isDeleteShown = false;
            return false;
        } else {
            return gestureDetector.onTouchEvent(event);
        }
    }

    @Override
    public boolean onDown(MotionEvent e) {
        if (!isDeleteShown) {
            selectedItem = pointToPosition((int) e.getX(), (int) e.getY());
        }
        return false;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        if (!isDeleteShown && Math.abs(velocityX) > Math.abs(velocityY)) {
            deleteButton = LayoutInflater.from(getContext()).inflate(R.layout.delete_button, null);
            deleteButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    itemLayout.removeView(deleteButton);
                    deleteButton = null;
                    isDeleteShown = false;
                    listener.onDelete(selectedItem);
                }
            });
            itemLayout = (ViewGroup) getChildAt(selectedItem - getFirstVisiblePosition());
            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
            params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
            params.addRule(RelativeLayout.CENTER_VERTICAL);
            itemLayout.addView(deleteButton, params);
            isDeleteShown = true;
        }
        return false;
    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return false;
    }

    @Override
    public void onShowPress(MotionEvent e) {
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        return false;
    }

    @Override
    public void onLongPress(MotionEvent e) {
    }

    public interface OnDeleteListener {
        void onDelete(int index);
    }
}

由于代碼邏輯比較簡(jiǎn)單抬纸,我就沒(méi)有加注釋咙俩。這里在MyListView的構(gòu)造方法中創(chuàng)建了一個(gè)GestureDetector的實(shí)例用于監(jiān)聽(tīng)手勢(shì),然后給MyListView注冊(cè)了touch監(jiān)聽(tīng)事件湿故。然后在onTouch()方法中進(jìn)行判斷阿趁,如果刪除按鈕已經(jīng)顯示了,就將它移除掉坛猪,如果刪除按鈕沒(méi)有顯示脖阵,就使用GestureDetector來(lái)處理當(dāng)前手勢(shì)。

當(dāng)手指按下時(shí)墅茉,會(huì)調(diào)用OnGestureListener的onDown()方法命黔,在這里通過(guò)pointToPosition()方法來(lái)判斷出當(dāng)前選中的是ListView的哪一行呜呐。當(dāng)手指快速滑動(dòng)時(shí),會(huì)調(diào)用onFling()方法悍募,在這里會(huì)去加載delete_button.xml這個(gè)布局蘑辑,然后將刪除按鈕添加到當(dāng)前選中的那一行item上。注意坠宴,我們還給刪除按鈕添加了一個(gè)點(diǎn)擊事件洋魂,當(dāng)點(diǎn)擊了刪除按鈕時(shí)就會(huì)回調(diào)onDeleteListener的onDelete()方法,在回調(diào)方法中應(yīng)該去處理具體的刪除操作喜鼓。

好了副砍,自定義View的功能到此就完成了荆萤,接下來(lái)我們需要看一下如何才能使用這個(gè)自定義View彩扔。首先需要?jiǎng)?chuàng)建一個(gè)ListView子項(xiàng)的布局文件,新建my_list_view_item.xml,代碼如下所示:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:descendantFocusability="blocksDescendants"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/text_view"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:layout_centerVertical="true"
        android:gravity="left|center_vertical"
        android:textColor="#000" />

</RelativeLayout>

然后創(chuàng)建一個(gè)適配器MyAdapter顿锰,在這個(gè)適配器中去加載my_list_view_item布局,代碼如下所示:

public class MyAdapter extends ArrayAdapter<String> {
    public MyAdapter(Context context, int textViewResourceId, List<String> objects) {
        super(context, textViewResourceId, objects);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view;
        if (convertView == null) {
            view = LayoutInflater.from(getContext()).inflate(R.layout.my_list_view_item, null);
        } else {
            view = convertView;
        }
        TextView textView = (TextView) view.findViewById(R.id.text_view);
        textView.setText(getItem(position));
        return view;
    }
}

到這里就基本已經(jīng)完工了启搂,下面在程序的主布局文件里面引入MyListView這個(gè)控件硼控,如下所示:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
    
<com.example.diyview.MyListView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/my_list_view">
    
</com.example.diyview.MyListView>

</RelativeLayout>

最后在Activity中初始化MyListView中的數(shù)據(jù),并處理了onDelete()方法的刪除邏輯胳赌,代碼如下所示:

public class MainActivity extends AppCompatActivity {

    private MyListView myListView;
    private MyAdapter adapter;
    private List<String> contentList = new ArrayList<String>();

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

        initList();
        myListView = (MyListView) findViewById(R.id.my_list_view);
        myListView.setOnDeleteListener(new MyListView.OnDeleteListener() {
            @Override
            public void onDelete(int index) {
                contentList.remove(index);
                adapter.notifyDataSetChanged();
            }
        });
        adapter = new MyAdapter(this, 0, contentList);
        myListView.setAdapter(adapter);
    }

    private void initList() {
        contentList.add("Content Item 1");
        contentList.add("Content Item 2");
        contentList.add("Content Item 3");
        contentList.add("Content Item 4");
        contentList.add("Content Item 5");
        contentList.add("Content Item 6");
        contentList.add("Content Item 7");
        contentList.add("Content Item 8");
        contentList.add("Content Item 9");
        contentList.add("Content Item 10");
        contentList.add("Content Item 11");
        contentList.add("Content Item 12");
        contentList.add("Content Item 13");
        contentList.add("Content Item 14");
        contentList.add("Content Item 15");
        contentList.add("Content Item 16");
        contentList.add("Content Item 17");
        contentList.add("Content Item 18");
        contentList.add("Content Item 19");
        contentList.add("Content Item 20");
    }
}

這樣就把整個(gè)例子的代碼都完成了牢撼,現(xiàn)在運(yùn)行一下程序,會(huì)看到MyListView可以像ListView一樣疑苫,正常顯示所有的數(shù)據(jù)熏版,但是當(dāng)你用手指在MyListView的某一行上快速滑動(dòng)時(shí),就會(huì)有一個(gè)刪除按鈕顯示出來(lái)捍掺,如下圖所示:


20190521_155517.gif

點(diǎn)擊一下刪除按鈕就可以將第6行的數(shù)據(jù)刪除了撼短。此時(shí)的MyListView不僅保留了ListView原生的所有功能,還增加了一個(gè)滑動(dòng)進(jìn)行刪除的功能挺勿,確實(shí)是一個(gè)不折不扣的繼承控件曲横。

到了這里,我們就把自定義View的幾種實(shí)現(xiàn)方法全部講完了不瓶,雖然每個(gè)例子都很簡(jiǎn)單禾嫉,但是萬(wàn)變不離其宗,復(fù)雜的View也是由這些簡(jiǎn)單的原理堆積出來(lái)的蚊丐。經(jīng)過(guò)了四篇文章的學(xué)習(xí)熙参,相信每個(gè)人對(duì)View的理解都已經(jīng)較為深入了,那么帶你一步步深入了解View系列的文章就到此結(jié)束麦备,感謝大家有耐心看到最后孽椰。

附:第一篇:Android LayoutInflater原理分析

附:第二篇:Android視圖繪制流程完全解析

附:第三篇:Android視圖狀態(tài)及重繪流程分析


作者:guolin
來(lái)源:CSDN
原文:https://blog.csdn.net/guolin_blog/article/details/12921889
版權(quán)聲明:本文為博主原創(chuàng)文章讲竿,轉(zhuǎn)載請(qǐng)附上博文鏈接!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末弄屡,一起剝皮案震驚了整個(gè)濱河市题禀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌膀捷,老刑警劉巖迈嘹,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異全庸,居然都是意外死亡秀仲,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門壶笼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)神僵,“玉大人,你說(shuō)我怎么就攤上這事覆劈”@瘢” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵责语,是天一觀的道長(zhǎng)炮障。 經(jīng)常有香客問(wèn)我,道長(zhǎng)坤候,這世上最難降的妖魔是什么胁赢? 我笑而不...
    開(kāi)封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮白筹,結(jié)果婚禮上智末,老公的妹妹穿的比我還像新娘。我一直安慰自己徒河,他們只是感情好系馆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著虚青,像睡著了一般它呀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上棒厘,一...
    開(kāi)封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天纵穿,我揣著相機(jī)與錄音,去河邊找鬼奢人。 笑死谓媒,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的何乎。 我是一名探鬼主播句惯,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼土辩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了抢野?” 一聲冷哼從身側(cè)響起拷淘,我...
    開(kāi)封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎指孤,沒(méi)想到半個(gè)月后启涯,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡恃轩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年结洼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片叉跛。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡松忍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出筷厘,到底是詐尸還是另有隱情鸣峭,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布敞掘,位于F島的核電站叽掘,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏玖雁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一盖腕、第九天 我趴在偏房一處隱蔽的房頂上張望赫冬。 院中可真熱鬧,春花似錦溃列、人聲如沸劲厌。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)补鼻。三九已至,卻和暖如春雅任,著一層夾襖步出監(jiān)牢的瞬間风范,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工沪么, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留硼婿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓禽车,卻偏偏與公主長(zhǎng)得像寇漫,于是被迫代替她去往敵國(guó)和親刊殉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

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