自定義View章办,微信視頻錄制進度條按鈕

效果圖.gif
效果圖.gif

2017/01/18
上海
Write endless of the View

  GitHub:https://github.com/ImmortalHalfWu/ViewSample/blob/master/app/src/main/java/com/viewsample/viewsample/views/ProgressButtonView.java

一批狐,樣式及事件分析

按鈕共有三種顯示樣式:
1,初始化狀態(tài)鸳谜,包含內(nèi)外兩個圓膝藕,靜態(tài)。
2咐扭,長按后芭挽,外圈拉伸,內(nèi)圈收縮草描,動態(tài)览绿。
3,外圈拉伸結(jié)束并且內(nèi)圈收縮結(jié)束穗慕,繪制進度條,動態(tài)妻导。


樣式圖.PNG

按鈕共有六種事件驅(qū)動:
1逛绵,初始化,控件加載倔韭。
2术浪,單擊,或者說短按寿酌。
3胰苏,短按抬手。
4醇疼,長按硕并。
5,長按抬手秧荆。
6倔毙,進度條加載結(jié)束。

事件與樣式的關(guān)系:
1乙濒,初始化陕赃、短按卵蛉、短按抬手,統(tǒng)一的初始化樣式么库。
2傻丝,長按,外圈拉伸诉儒,內(nèi)圈收縮葡缰,之后繪制進度條。
3允睹,長按抬手运准、進度條加載結(jié)束,恢復為初始化樣式缭受。

事件回調(diào):
1胁澳,短按,短按抬手時回調(diào)米者。
2韭畸,長按按下,判斷為長按后立刻回調(diào)蔓搞。
3胰丁,長按抬起時回調(diào)。
4喂分,進度條結(jié)束時回調(diào)锦庸。
5,長按后蒲祈,手指滑動時回調(diào)甘萧。

二,模塊劃分

1梆掸,StateMachine狀態(tài)機 + 低配MVC + 回調(diào)接口
StateMachine狀態(tài)機 : 描述所有狀態(tài)扬卷,并記錄當下所處狀態(tài)。
View : 測量自身寬高酸钦,繪制圖形怪得,接收觸屏事件。
Model : 記錄數(shù)值卑硫,例如控件寬高徒恋,以及繪制圖形時的數(shù)值。
Controller : 處理觸屏事件拔恰,針對事件修改Model數(shù)據(jù)因谎,并通知View重繪。
CallBackListener:回調(diào)接口颜懊,將控件的不同狀態(tài)及事件傳遞給外部财岔。

流程:
1风皿,初始化StateMachine、Model匠璧、Controller桐款。
2,獲取Model數(shù)值繪制圖形夷恍。
3魔眨,接受觸屏事件。
4酿雪,修改狀態(tài)遏暴。
5,Controller根據(jù)狀態(tài)修改Model繪制數(shù)值指黎。
6朋凉,通知View重繪。
7醋安,如果外部傳入了回調(diào)接口杂彭,則回調(diào)。

三吓揪,自上而下的抽象

StateMachine亲怠,狀態(tài)機。

    /**
     * 狀態(tài)機柠辞,描述不同的狀態(tài)
     */
    public enum StateMachine{

        /**
         * 初始化狀態(tài)
         */
        STATE_INITIA,
        /**
         * 短按
         */
        STATE_SHORT_CLICK,
        /**
         * 短按抬手
         */
        STATE_SHORT_UP,
        /**
         * 長按中
         */
        STATE_LONG_CLICKING,
        /**
         * 長按抬手
         */
        STATE_LONG_UP,
        /**
         * 進度條加載結(jié)束
         */
        STATE_PROGRESS_OVER,

    }

CallBackListener团秽,回調(diào)接口.


    /**
     * 事件回調(diào)接口
     */
    public interface CallBackListener{

        /**
         * 短按,抬手時回調(diào)
         */
        void shortClick();

        /**
         * 長按叭首,判斷為長按后回調(diào)
         */
        void longClick();

        /**
         * 長按抬起徙垫,與{@link #progressOver()}只有一個會回調(diào)
         */
        void longClickUp();

        /**
         * 進度條結(jié)束 ,與{@link #longClickUp()}只有一個會回調(diào)
         */
        void progressOver();

        /**
         * 手指滑動放棒,只有在長按中滑動才會調(diào)用
         * @param event
         */
        void move(MotionEvent event);

    }

View , 重點在于觸屏與圖形繪制,基于責任劃分的目的己英,View本身應盡量避免不同狀態(tài)下或不同事件下數(shù)值的計算间螟。

//計算寬高,注意到控件是有伸縮效果的损肛,所以得到的寬高應該是拉伸后的寬高
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  //計算拉伸后的寬高
}
//繪制圖形厢破,并只負責繪制圖形,圖形的參數(shù)數(shù)值不在此處理
protected void onDraw(Canvas canvas) {
  //外圓
  //進度條
  //內(nèi)圓
}
//觸屏監(jiān)聽
public boolean onTouchEvent(MotionEvent event) {
  //根據(jù)事件修改View所處的狀態(tài)
}
//銷毀
protected void onDetachedFromWindow(){
  //釋放資源
}

Model治拿,記錄繪制數(shù)值摩泪。(為了避免又多又長的變量名所造成的不適,變量以大白話漢字表示)

"控件寬度"
"控件高度"
"初始化時內(nèi)圓半徑" //初始化時的內(nèi)圓半徑
"初始化時外圓半徑" //初始化時的外圓半徑
"長按狀態(tài)內(nèi)圓半徑" //長按狀態(tài)下內(nèi)圓半徑
"長按狀態(tài)外圓半徑" //長按狀態(tài)下外圓半徑
"繪制時使用的內(nèi)圓半徑" //大于等于最小內(nèi)圓半徑劫谅,小于等于最大內(nèi)圓半徑
"繪制時使用的外圓半徑" //大于等于最小外圓半徑见坑,小于等于最大外圓半徑
"進度條寬度"
"進度條弧度"
"進度條最長時間"

"外圓顏色"
"內(nèi)圓顏色"
"進度條顏色"

Controller嚷掠,控制器,根據(jù)狀態(tài)的不同荞驴,對Model數(shù)值進行不同的計算不皆,之后刷新界面。
使用線程作為Controller熊楼,缺點是為了避免浪費CPU霹娄,需要掌控好線程的等待與喚醒,并且有駁于MVC的設(shè)計鲫骗,好處是沒必要在重復繪制形成動畫結(jié)束后反復new Thread()犬耻。

//使用線程作為Controller
public class PoorThread extends Thread{
  public void run() {
    //針對不同的狀態(tài),進行不同的數(shù)值計算执泰,并刷新界面
  }
  //線程等待
  public void waitPoorThread(){
          if ("是否處于等待狀態(tài)") return;
            synchronized (PoorThread.this){
                try {
                    "是否處于等待狀態(tài)"= true;
                    //等待
                    PoorThread.this.wait();
                } catch (InterruptedException e) {
                    "是否處于等待狀態(tài)"= false;
                    e.printStackTrace();
                }
            }
  }
  //線程喚醒
  public void noitfyPoorThread(){
            if (!"是否處于等待狀態(tài)") return;
            synchronized (PoorThread.this){
                //喚醒
                PoorThread.this.notify();
                "是否處于等待狀態(tài)"= false;
            }
  }
}

四枕磁,自下而上的實現(xiàn)

1,View層坦胶,寬高計算透典、樣式繪制、接收觸摸事件及釋放資源

寬高計算:
因為樣式核心是圓顿苇,為了省去不必要的麻煩峭咒,所以設(shè)定寬高相等(并不是必須相等)

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        //screenWid 為屏幕寬度
        //screenHei 為屏幕高度

        int widMod = MeasureSpec.getMode(widthMeasureSpec);
        int heiMod = MeasureSpec.getMode(heightMeasureSpec);
        //指定寬
        if (widMod == MeasureSpec.EXACTLY){
            //獲取指定寬
            mWidth = MeasureSpec.getSize(widthMeasureSpec);
        }
        //指定最大寬度
        else if (widMod == MeasureSpec.AT_MOST){
            //如果屏幕屏幕寬度/3大于指定最大寬度,則取最大寬度
            mWidth = MeasureSpec.getSize(widthMeasureSpec) < screenWid / 3 ? MeasureSpec.getSize(widthMeasureSpec) : screenWid / 3;
        }
        //未指定寬度
        else if (widMod == MeasureSpec.UNSPECIFIED){
            //則取屏幕寬度/3
            mWidth = screenWid / 3;
        }

        //高度同上
        if (heiMod == MeasureSpec.EXACTLY){
            mHeight = MeasureSpec.getSize(heightMeasureSpec);
        }else if (heiMod == MeasureSpec.AT_MOST){
            mHeight = MeasureSpec.getSize(heightMeasureSpec) < screenHei / 3 ? MeasureSpec.getSize(heightMeasureSpec) : screenHei / 3;
        }else if (heiMod == MeasureSpec.UNSPECIFIED){
            mHeight = screenHei / 3;
        }

        //求出寬高后纪岁,需要加上內(nèi)邊距凑队,之后寬高取小(避免橫豎屏切換帶來的麻煩)幔翰,因為控件是正方形漩氨,變量mSize是為了使用方便
        mSize = mHeight = mWidth = Math.min(mHeight + getPaddingTop() + getPaddingBottom(),mWidth + getPaddingLeft() + getPaddingRight());

        setMeasuredDimension(mWidth,mHeight);
        //計算出寬高后,計算Model中數(shù)據(jù)
        initValue();
}
//初始化Model數(shù)據(jù)
private void initValue() {

         //mSize = "控件寬高取小";

        "初始化時外圓半徑"= mSize/3;
        "長按狀態(tài)外圓半徑"= mSize/2;

        "初始化時內(nèi)圓半徑"= mSize/4;
        "長按狀態(tài)內(nèi)圓半徑" = mSize/6;

        "繪制時使用的內(nèi)圓半徑"= "初始化時外圓半徑";
        "繪制時使用的外圓半徑"=  "初始化時內(nèi)圓半徑";

        "進度條寬度"= mSize/25;
        "進度條弧度"= 0;
}

樣式繪制(代碼里雙引號中的漢字并不是字符串遗增,而是指代某個變量):
View的繪制順序遵循后來居上叫惊,先畫的會被后畫的遮蓋。

//長按狀態(tài)下同初始化狀態(tài)一樣內(nèi)外圓還是存在的做修,只是多了進度條霍狰。
//對于進度條,簡單的實現(xiàn)方式是先畫實心弧饰及,再在弧上畫圓蔗坯,
//圓的顏色為背景色,圓的半徑小于弧的半徑燎含,
//這樣會遮蓋弧的內(nèi)部宾濒,只留外部的一圈,達到弧線的效果屏箍。
//這樣的實現(xiàn)方式無需考慮畫筆的寬度绘梦,也省去了計算寬高時的麻煩橘忱。

//在這個控件中,由底部到頂部的繪制順序是:
//1谚咬,外圓鹦付。    2,弧择卦。    3敲长,遮蓋弧的圓(與外圓顏色相等)    4,內(nèi)圓秉继。

//而進度條是在外圓拉伸結(jié)束祈噪、內(nèi)圓收縮結(jié)束后才出現(xiàn),所以需要加判斷
//1尚辑,外圓辑鲤。    
//if(外圓拉伸結(jié)束、內(nèi)圓收縮結(jié)束) {   2杠茬,弧月褥。    3,遮蓋弧的圓(與外圓顏色相等)    }
//4瓢喉,內(nèi)圓宁赤。


//畫外圓
mPaint.setColor("外圓的顏色");
canvas.drawCircle(
      canvas.getWidth() / 2,  //繪制在控件正中
      canvas.getHeight() /2,
      "繪制時使用的外圓半徑",
      mPaint
);

//當前狀態(tài)為長按中,并且進度條弧度大于0栓票,才繪制進度條
if( "如果當前狀態(tài)為長按中" && "進度條弧度" > 0  ){

      //畫弧
      mPaint.setColor("進度條顏色");
      canvas.drawArc(
            //RectF 應為成員變量决左,在此簡寫
            new RectF(canvas.getWidth()/2- "繪制時使用的外圓半徑",
                    canvas.getHeight()/2- "繪制時使用的外圓半徑" ,
                    canvas.getWidth()/2+ "繪制時使用的外圓半徑" ,
                    canvas.getHeight()/2+ "繪制時使用的外圓半徑" ),
            -90.0f,
            "進度條弧度",
            true,
            mPaint
      );

      //畫遮蓋弧線的圓
      mPaint.setColor("外圓的顏色");
      //畫在正中心,半徑為長按狀態(tài)下外圓最大半徑 - 進度條寬度走贪,也就是遮蓋的半徑
      canvas.drawCircle(
            canvas.getWidth() / 2,
            canvas.getHeight() /2,
            "長按狀態(tài)下外圓最大半徑" - "進度條寬度",
            mPaint
      );

}


//畫內(nèi)圓
mPaint.setColor("內(nèi)圓的顏色");
canvas.drawCircle(
      canvas.getWidth() / 2,  //繪制在控件正中
      canvas.getHeight() /2,
      "繪制時使用的內(nèi)圓半徑",
      mPaint
);

觸摸事件處理:
主要任務(wù)是根據(jù)手勢修改控件所處的狀態(tài)佛猛。

public boolean onTouchEvent(MotionEvent event) {

    switch(event.getAction()){

      //手指按下
      case MotionEvent.ACTION_DOWN:
      //如果不是初始狀態(tài),則直接返回坠狡,因為動畫需要時間继找,避免沖突
        if("當前狀態(tài)" != StateMachine.STATE_INITIA){
           return  false;
        }
        //將狀態(tài)切換為短按
        "當前狀態(tài)"  = StateMachine.STATE_SHORT_CLICK;
        //調(diào)用線程,250毫秒后運行逃沿,如果狀態(tài)還是短按而沒有抬手码荔,則將狀態(tài)切換為長按。
        //(此Runnable應為成員變量感挥,在此簡寫)
        postDelayed(new Runnable(){
          @Override
          public void run() {
            //如果當前狀態(tài)為短按
            if ("當前狀態(tài)"== StateMachine.STATE_SHORT_CLICK){
                //切換為長按
                "當前狀態(tài)" = StateMachine.STATE_LONG_CLICKING;
                //喚醒數(shù)據(jù)處理線程
                if (mPoorThread!= null){
                    mPoorThread.noitfyPoorThread();
                }
                //如果回調(diào)接口不為空,回調(diào)接口
                if (mCallBackListener != null){
                    mCallBackListener.longClick();
                }
            }
          }
        },250);
      break;


      //手指移動
      case case MotionEvent.ACTION_MOVE:
      //如果外部傳入回調(diào)接口并且越败,當前狀態(tài)為長按中
      if(mCallBackListener!= null 
          && "當前狀態(tài)"== StateMachine.STATE_LONG_CLICKING){
          //接口回調(diào)
          mCallBackListener.move(event);
       }
      break;


      //手指抬起
      case MotionEvent.ACTION_UP:
      //如果當前狀態(tài)為短按触幼,
      if (mStateMachine == StateMachine.STATE_SHORT_CLICK){
        //則更當前改狀態(tài)為短按抬起
        "當前狀態(tài)"= StateMachine.STATE_SHORT_UP;
        //如果傳入了回調(diào)接口
        if (mCallBackListener != null){
               //回調(diào)
               mCallBackListener.shortClick();
        }
        //回調(diào)結(jié)束后,將當前狀態(tài)切換位初始化
        "當前狀態(tài)"= StateMachine.STATE_INITIA;
      }
      //如果狀態(tài)為長按究飞,
      if ("當前狀態(tài)"== StateMachine.STATE_LONG_CLICKING){
         //則更改當前狀態(tài)為長按抬起
         "當前狀態(tài)"= StateMachine.STATE_LONG_UP;
         //回調(diào)結(jié)束
      }
      break;
    }
}

釋放資源置谦,關(guān)閉循環(huán)線程堂鲤,清空成員變量。

@Override
    protected void onDetachedFromWindow() {
        //銷毀
        
        mStateMachine = null;
        if (mPaint != null){
            mPaint.reset();
            mPaint = null;
        }
        //mClickIntervalRunnable時判斷長短按的Runnable
        if (mClickIntervalRunnable!=null){
            mClickIntervalRunnable = null;
        }
        if (mCallBackListener != null){
            mCallBackListener = null;
        }
        if (mPoorThread != null){
            mPoorThread.finishPoorThread();
        }

        super.onDetachedFromWindow();
    }

2媒峡,Controller層瘟栖,根據(jù)當前狀態(tài),修改數(shù)據(jù)及刷新界面

   /**
     * 控制數(shù)據(jù)谅阿,重復刷新控件
     */
    private final class PoorThread extends Thread{

        private static final String TAG = ProgressButtonView.TAG+".PoorThread";
        //默認死循環(huán)
        private boolean "線程開關(guān)"= true;
        private boolean "是否處于等待狀態(tài)"= false;
        /**
         * 刷新間隔ms
         */
        private int sleepTime = 13;

        PoorThread(){
            setName(TAG);
            //因為線程實在初始化時new的半哟,當控件狀態(tài)為初始化時,會保持wait签餐,所以可以直接啟動寓涨。
            start();
        }

        @Override
        public void run() {

            //默認死循環(huán),控件銷毀時停止
            while ("線程開關(guān)"){
                switch ("當前狀態(tài)"){

                    case STATE_INITIA://初始化
                    case STATE_SHORT_CLICK://短按
                    case STATE_SHORT_UP://短按抬起
                        //如果是初始化氯檐、短按戒良、短按抬起三種狀態(tài),則wait線程
                        waitPoorThread();
                        break;

                    //長按ing
                    case STATE_LONG_CLICKING:
                        //長按后冠摄,拉伸外圈糯崎,收縮內(nèi)圈,如果外圈半徑小于指定最大半徑河泳,或內(nèi)圈半徑大于指定最小半徑沃呢,則修改半徑數(shù)值,并刷新界面
                        if ("繪制時使用的外圓半徑"< "長按狀態(tài)外圓半徑"|| "繪制時使用的內(nèi)圓半徑"> "長按狀態(tài)內(nèi)圓半徑"){
                            //增加外圈半徑乔询,每次更改的數(shù)值相同
                            "繪制時使用的外圓半徑"+= ( "長按狀態(tài)外圓半徑"- "初始化時外圓半徑") / sleepTime;
                            //確保更改后的數(shù)值<=指定最大半徑樟插,如果大于,則賦值外圓最大半徑
                            "繪制時使用的外圓半徑"= "繪制時使用的外圓半徑"> "長按狀態(tài)外圓半徑"?  "長按狀態(tài)外圓半徑": "繪制時使用的外圓半徑";
                            //減小內(nèi)圈半徑竿刁,每次更改的數(shù)值相同
                            "繪制時使用的內(nèi)圓半徑"+= ("長按狀態(tài)內(nèi)圓半徑"- "初始化時內(nèi)圓半徑") / sleepTime;
                            //確保更改后的數(shù)值>=指定最小半徑黄锤,如果小于,則賦值內(nèi)圈最小半徑
                             "繪制時使用的內(nèi)圓半徑"=  "繪制時使用的內(nèi)圓半徑" < "長按狀態(tài)內(nèi)圓半徑"? "長按狀態(tài)內(nèi)圓半徑": "繪制時使用的內(nèi)圓半徑" ;
                        }
                        //如果當前外圈半徑==最大外圈半徑食拜,并且內(nèi)圈半徑==最小內(nèi)圈半徑鸵熟,則說明伸縮動畫結(jié)束
                        //如果弧線的角度小于360,則進度條還沒加載結(jié)束负甸,繼續(xù)加載進度條
                        else if ("進度條弧度"< 360){
                            //則增加弧線角度流强,確保每次更改數(shù)值相同
                            "進度條弧度"+= 360.0f / "進度條最長時間"* sleepTime;
                            //確保角度<=360
                            "進度條弧度"= "進度條弧度">360 ? 360 : "進度條弧度";
                        }
                        //拉伸動畫結(jié)束,弧線角度>=360呻待,則進度條加載結(jié)束
                        else if ("進度條弧度">= 360){
                            //狀態(tài)切換為進度條加載結(jié)束
                            "當前狀態(tài)"= StateMachine.STATE_PROGRESS_OVER;
                        }

                        break;

                    //長按抬手與進度條結(jié)束兩種狀態(tài)的處理方式一樣打月,收縮外圈,拉伸內(nèi)圈蚕捉,以動畫的形式過度到初始狀態(tài)
                    case STATE_PROGRESS_OVER://進度條加載結(jié)束
                    case STATE_LONG_UP://長按抬手

                        //進度條寬度為0奏篙,也就相當于不繪制
                        "進度條弧度"= 0;

                        //抬手或進度條結(jié)束,外圓收縮,內(nèi)圓拉伸秘通,判斷外圓是否大于初始值为严,內(nèi)院是否小于初始值,如果是肺稀,則更改數(shù)據(jù)
                        if ("繪制時使用的外圓半徑"> "初始化時外圓半徑"|| "繪制時使用的內(nèi)圓半徑" < "初始化時內(nèi)圓半徑"){
                            //確保外圓半徑每次更改的數(shù)值相同
                            "繪制時使用的外圓半徑"+= ("初始化時外圓半徑" - "長按狀態(tài)外圓半徑") / sleepTime;
                            //確保外圓半徑更改后的數(shù)值<=指定數(shù)值
                            "繪制時使用的外圓半徑" = "繪制時使用的外圓半徑" < "初始化時外圓半徑"?  "初始化時外圓半徑": "繪制時使用的外圓半徑" ;
                            //確保每次更改的數(shù)值相同
                            "繪制時使用的內(nèi)圓半徑"+= ("初始化時內(nèi)圓半徑"- "長按狀態(tài)內(nèi)圓半徑" ) / sleepTime;
                            //確保更改后的數(shù)值>=指定數(shù)值
                             "繪制時使用的內(nèi)圓半徑"=  "繪制時使用的內(nèi)圓半徑"> "初始化時內(nèi)圓半徑"? "初始化時內(nèi)圓半徑":  "繪制時使用的內(nèi)圓半徑";
                        }
                        //伸縮動畫結(jié)束
                        else{
                            //如果接口不為空
                            if (mCallBackListener != null){
                                //如果當前狀態(tài)為進度條結(jié)束
                                if ("當前狀態(tài)"== StateMachine.STATE_PROGRESS_OVER){
                                    //狀態(tài)為進度條結(jié)束第股,回調(diào)
                                    mCallBackListener.progressOver();
                                }else{
                                    //否則就是長按抬手,回調(diào)
                                    mCallBackListener.longClickUp();
                                }

                            }
                            //如果內(nèi)外圓都恢復為初始大小话原,則將狀態(tài)切換為初始狀態(tài)
                            "當前狀態(tài)"= StateMachine.STATE_INITIA;
                        }

                        break;

                }

                try {
                    sleep(sleepTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    break;
                }
                //刷新界面
                postInvalidate();

            }


        }

  /**
  * 銷毀線程
  */
  public void finishPoorThread(){
       "線程開關(guān)"= false;
       noitfyPoorThread();
  }


  //線程等待
  public void waitPoorThread(){
          if ("是否處于等待狀態(tài)") return;
            synchronized (PoorThread.this){
                try {
                   "是否處于等待狀態(tài)"= true;
                    //等待
                    PoorThread.this.wait();
                } catch (InterruptedException e) {
                    "是否處于等待狀態(tài)" = false;
                    e.printStackTrace();
                }
            }
  }
  //線程喚醒
  public void noitfyPoorThread(){
            if (!"是否處于等待狀態(tài)") return;
            synchronized (PoorThread.this){
                //喚醒
                PoorThread.this.notify();
                "是否處于等待狀態(tài)"= false;
            }
  }

}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末夕吻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子稿静,更是在濱河造成了極大的恐慌梭冠,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件改备,死亡現(xiàn)場離奇詭異控漠,居然都是意外死亡,警方通過查閱死者的電腦和手機悬钳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門盐捷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人默勾,你說我怎么就攤上這事碉渡。” “怎么了母剥?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵滞诺,是天一觀的道長。 經(jīng)常有香客問我环疼,道長习霹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任炫隶,我火速辦了婚禮淋叶,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘伪阶。我一直安慰自己煞檩,他們只是感情好,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布栅贴。 她就那樣靜靜地躺著斟湃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪檐薯。 梳的紋絲不亂的頭發(fā)上桐早,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天,我揣著相機與錄音,去河邊找鬼哄酝。 笑死,一個胖子當著我的面吹牛祷膳,可吹牛的內(nèi)容都是我干的陶衅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼直晨,長吁一口氣:“原來是場噩夢啊……” “哼搀军!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起勇皇,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤罩句,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后敛摘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體门烂,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年兄淫,在試婚紗的時候發(fā)現(xiàn)自己被綠了屯远。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡捕虽,死狀恐怖慨丐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情泄私,我是刑警寧澤房揭,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站晌端,受9級特大地震影響捅暴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜斩松,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一伶唯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧惧盹,春花似錦乳幸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至嫡霞,卻和暖如春瓶埋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工养筒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留曾撤,地道東北人。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓晕粪,卻偏偏與公主長得像挤悉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子巫湘,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

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