Android 今日頭條下拉刷新實(shí)現(xiàn)

前言

前兩天在玩今日頭條,覺得今日頭條的下拉刷新蠻有意思的牍疏,就自己實(shí)現(xiàn)了一下挚赊,整體上實(shí)現(xiàn)了同樣的效果。無圖無真相触机,效果圖如下:
今日頭條效果:


image

實(shí)現(xiàn)效果:


image

項(xiàng)目地址 TodayNewsHeader

實(shí)現(xiàn)過程分為兩部分:

  • 圖形繪制
  • 結(jié)合下拉刷新動(dòng)起來

圖形繪制

測量,坐標(biāo)計(jì)算

實(shí)現(xiàn)過程中圖形的繪制全部是通過Path 完成玷或,需要精確計(jì)算 path 各個(gè)部分的坐標(biāo)值

對(duì)Path不熟悉的請(qǐng)看Path使用詳解

這里需要注意的是:在繪制時(shí)坐標(biāo)不能從 0 開始儡首,繪制線條是通過Paint.setStyle(Paint.Style.STROKE)方法,如果從0開始繪制 會(huì)出現(xiàn)左側(cè)偏友,頂部線條只能繪制一半的情況
主要參數(shù):

  private int strokeWidth;  //線寬
    //繪制不能從  坐標(biāo)0 開始 會(huì)有 stroke*1 的偏移量
    private int contentWidth, contentHeight;  //內(nèi)容寬度 內(nèi)容高度
    private float roundCorner;  //外層 圓角矩形 圓角半徑
    private float lineWidth;  // 線條寬度
    private float rectWidth;  //小矩形寬度
    private float shortLineWidth; //短線寬度
    private float spaceRectLine;  //小矩形距 斷線距離

坐標(biāo)說明圖:


image

特地說明一下 roundCorner: 為 圓角矩形的圓角
在這里將 contentHeight 分為 7等份蔬胯,roundCorner 為 1/7的contentHeight
之后每個(gè)線條之間間距 一個(gè) roundCorner

測量計(jì)算關(guān)鍵變量代碼:


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);

        int width = MeasureSpec.getSize(widthMeasureSpec);


        int heightMode = MeasureSpec.getMode(heightMeasureSpec);


        int height = MeasureSpec.getSize(heightMeasureSpec);

        
        //設(shè)定最小值時(shí),增加 stoke 的偏移保證 邊界繪制完整
        int minWidth = dip2px(30) + strokeWidth * 2;

        int minHeight = dip2px(35) + strokeWidth * 2;

        //判斷 測量模式  如果是  wrap_content 需要對(duì) 寬高進(jìn)行限定
        //同時(shí)確定 高度 也對(duì) 最小值進(jìn)行限定

        if (widthMode == MeasureSpec.AT_MOST) {
            width = minWidth;
        } else if (widthMode == MeasureSpec.EXACTLY && width < minWidth) {
            width = minWidth;
        }

        if (heightMode == MeasureSpec.AT_MOST) {
            height = minHeight;
        } else if (heightMode == MeasureSpec.EXACTLY && height < minHeight) {
            height = minHeight;
        }

        // 在確定寬高之后 對(duì)內(nèi)容 寬高再次進(jìn)行計(jì)算位他,留出 stroke 的偏移
        contentWidth = width - strokeWidth * 2;

        contentHeight = height - strokeWidth * 2;

        setMeasuredDimension(width, height);

        initNeedParamn();
        //初始化最外層 圓角矩形 path
        initPath();
    }

    /**
     * 初始化繪制所需要的參數(shù)
     */
    private void initNeedParamn() {
        //圓角半徑
        roundCorner = contentHeight / 7f;
        //線條寬度
        lineWidth = contentWidth - roundCorner * 2;
        //小矩形寬度
        rectWidth = lineWidth / 2f;
        //短線寬度
        shortLineWidth = (lineWidth / 8f) * 3f;  //短線條寬度
        //矩形與 斷線之間的間距
        spaceRectLine = (lineWidth / 8f) * 1f; //矩形與線條之間間距
    }
繪制

通過觀察進(jìn)入頭條gif 效果氛濒,圖形的繪制分為兩部分

  • 拖拽過程繪制
  • 刷新過程繪制

在兩個(gè)過程中,最外層圓角矩形是不變的鹅髓,先來繪制這個(gè)圓角矩形舞竿。最外層圓角矩形Path初始化:

private Path roundPath; //最外層 圓形Path
/**
     * 初始化 path
     */
    private void initPath() {


        roundPath = new Path();
        //從右側(cè)第一個(gè)圓角作為起點(diǎn)
        roundPath.moveTo(contentWidth, roundCorner);
        roundPath.arcTo(contentWidth - roundCorner * 2, 0, contentWidth, roundCorner * 2, 0, -90, false);
        roundPath.lineTo(roundCorner, 0);
        roundPath.arcTo(0, 0, roundCorner * 2, roundCorner * 2, -90, -90, false);
        roundPath.lineTo(0, contentHeight - roundCorner);
        roundPath.arcTo(0, contentHeight - roundCorner * 2, roundCorner * 2, contentHeight, -180, -90, false);
        roundPath.lineTo(contentWidth - roundCorner, contentHeight);
        roundPath.arcTo(contentWidth - roundCorner * 2, contentHeight - roundCorner * 2, contentWidth, contentHeight, -270, -90, false);
  //path閉合 自動(dòng) lineTo(contentWidth, roundCorner)
        roundPath.close();
    }

小矩形與線條Path創(chuàng)建

測量完成后,需要的參數(shù)已經(jīng)計(jì)算完成窿冯,我們可以根據(jù)指定坐標(biāo)提供小矩形和線條的Path

 /**
     * 根據(jù) 左上 坐標(biāo) 創(chuàng)建 矩形 Path
     *
     * @param left 左坐標(biāo)
     * @param top  上坐標(biāo)
     * @return
     */
    public Path provideRectPath(float left, float top) {
        Path path = new Path();
        path.moveTo(left + rectWidth, top);
        path.lineTo(left, top);
        path.lineTo(left, top + roundCorner * 2f);
        path.lineTo(left + rectWidth, top + roundCorner * 2f);
        path.close();
        return path;
    }


    /**
     * 根據(jù)線條 左上 坐標(biāo)和線寬創(chuàng)建線條 Path
     *
     * @param left 左坐標(biāo)
     * @param top  上坐標(biāo)
     * @param lineWidth  線寬
     * @return
     */
    public Path provideLinePath(float left, float top, float lineWidth) {
        Path path = new Path();
        path.moveTo(left, top);
        path.lineTo(left + lineWidth, top);
        return path;
    }

每個(gè)圖形都是通過Path繪制骗奖,對(duì)每個(gè)繪制的狀態(tài)進(jìn)行封裝

 /**
     * 繪制的狀態(tài)
     */
    public abstract class State {

        protected List<PathWrapper> mPathList;

        public State() {
            mPathList = new ArrayList<>();
            initStatePath();
        }
         //初始化 PathWrapper集合
        protected abstract void initStatePath();
        
        //將繪制分配給 PathWrapper執(zhí)行
        void onDraw(Canvas canvas, Paint paint) {
            for (PathWrapper path : mPathList) {
                path.onDraw(canvas, paint);
            }
        }
    }

這里的 PathWrapper 會(huì)在下面的拖拽過程進(jìn)行解釋

拖拽過程

下拉拖拽過程:

image

頭部刷新View 跟隨手指下拉顯示,當(dāng)下拉高度超過了一定距離醒串,Path圖形開始繪制执桌,手指繼續(xù)下拉 ,圖形繪制完全芜赌,并且可以看到會(huì)有一個(gè)漸進(jìn)繪制的效果仰挣。這里需要根據(jù)下拉率 fraction來計(jì)算繪制比例

漸進(jìn)繪制分析
每個(gè)圖形根據(jù) fraction 的繪制比例是不同的,我在這里設(shè)計(jì)的映射關(guān)系如下表:

圖形 fraction 繪制比例
外層圓角矩形 0~1 0~1
矩形 0~0.25 0~1
短線條1 0.25~0.33 0~1
短線條2 0.33~0.41 0~1
短線條3 0.41~0.5 0~1
長線條1 0.5~0.66 0~1
長線條2 0.66~0.82 0~1
長線條3 0.82~1 0~1

這里需要公式去計(jì)算每個(gè)圖形的繪制比例较鼓,并且需要一個(gè)容器去保存每個(gè)圖形的path 和繪制比例椎木,PathWrapper 就應(yīng)運(yùn)而生。

public class PathWrapper {
    protected Path mPath; //圖形 Path
    protected float fraction;  //繪制的比例


    public PathWrapper(Path path, float fraction) {
        mPath = path;
        this.fraction = fraction;
    }


    public void onDraw(Canvas canvas, Paint paint) {
        if(fraction<=0) {
            return;
        }

        Path dst = new Path();
        PathMeasure measure = new PathMeasure(mPath, false);         // 將 Path 與 PathMeasure 關(guān)聯(lián)

        float length = measure.getLength();

        // 截取一部分 并使用 moveTo 保持截取得到的 Path 第一個(gè)點(diǎn)的位置不變
        measure.getSegment(0, length*fraction, dst, true);

        canvas.drawPath(dst, paint);
    }
}

PathWrapper 保存了path 和 繪制比例博烂。
這里有一個(gè)巧妙的設(shè)計(jì)是將 圖形的繪制 封裝到了 PathWrapper中香椎,這么早的好處在哪里呢?不要急禽篱,接下來會(huì)分析到畜伐。而關(guān)于繪制代碼有問題的可以參考 Path使用詳解

image

這個(gè)圖形可以看到 小矩形有一個(gè)灰色的填充效果,與其他圖形的繪制有所分別躺率,就不能使用通用的繪制方法進(jìn)行繪制玛界,需要特殊對(duì)待万矾。
這時(shí)候PathWrapper 封裝 繪制代碼的作用就提現(xiàn)了出來,對(duì)于線條圖形使用通用的方法慎框,對(duì)于矩形圖形良狈,創(chuàng)建單獨(dú)的 RectPathWrapper 繼承自PathWrapper對(duì) public void onDraw(Canvas canvas, Paint paint)方法進(jìn)行重寫,自定義繪制規(guī)則笨枯。

public class RectPathWrapper extends PathWrapper {

    Paint mPaint;

    public RectPathWrapper(Path path, float fraction) {
        super(path, fraction);
        //創(chuàng)建新的畫筆  設(shè)置填充樣式    顏色
         mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(0x32000000);
    }


    public void onDraw(Canvas canvas, Paint paint) {
        if (fraction <= 0) {
            return;
        }

        Path dst = new Path();
        PathMeasure measure = new PathMeasure(mPath, false);         // 將 Path 與 PathMeasure 關(guān)聯(lián)

        float length = measure.getLength();

        measure.getSegment(0, length * fraction, dst, true);                   // 截取一部分 并使用 moveTo 保持截取得到的 Path 第一個(gè)點(diǎn)的位置不變
        //繪制線條
        canvas.drawPath(dst, paint);
         //繪制填充
        canvas.drawPath(dst, mPaint);
    }
}

關(guān)于繪制比例計(jì)算
再看一次映射關(guān)系

圖形 fraction 繪制比例
外層圓角矩形 0~1 0~1
矩形 0~0.25 0~1
短線條1 0.25~0.33 0~1
短線條2 0.33~0.41 0~1
短線條3 0.41~0.5 0~1
長線條1 0.5~0.66 0~1
長線條2 0.66~0.82 0~1
長線條3 0.82~1 0~1

直接貼出 DragState的代碼

 class DragState extends State {


        private float fraction = 0f;


        public void setFraction(float fraction) {
            this.fraction = fraction;
            mPathList.clear();
            initStatePath();
        }
        
        @Override
        protected void initStatePath() {
            //圓角 矩形 
            PathWrapper pathWrapper = new PathWrapper(roundPath, fraction);
            mPathList.add(pathWrapper);

            //小矩形
            Path rectPath = provideRectPath(roundCorner, roundCorner);
            pathWrapper = new RectPathWrapper(rectPath, Math.min(1, 4 * fraction));
            mPathList.add(pathWrapper);

            //短線條1
            float shortLeft = roundCorner + rectWidth + spaceRectLine;
            Path shortLine1 = provideLinePath(shortLeft, roundCorner, shortLineWidth);
            pathWrapper = new PathWrapper(shortLine1, Math.min(1, 12.5f * (fraction - 0.25f)));
            mPathList.add(pathWrapper);

//

             //短線條2
            Path shortLine2 = provideLinePath(shortLeft, roundCorner * 2f, shortLineWidth);
            pathWrapper = new PathWrapper(shortLine2, Math.min(1, 12.5f * (fraction - 0.33f)));
            mPathList.add(pathWrapper);
//
             //短線條3
            Path shortLine3 = provideLinePath(shortLeft, roundCorner * 3f, shortLineWidth);
            pathWrapper = new PathWrapper(shortLine3, Math.min(1, 12.5f * (fraction - 0.41f)));
            mPathList.add(pathWrapper);
//
            //長線條1
            Path longLine1 = provideLinePath(roundCorner, roundCorner * 4f, lineWidth);
            pathWrapper = new PathWrapper(longLine1, Math.min(1, 6.25f * (fraction - 0.5f)));
            mPathList.add(pathWrapper);
            //長線條2
            Path longLine2 = provideLinePath(roundCorner, roundCorner * 5f, lineWidth);
            pathWrapper = new PathWrapper(longLine2, Math.min(1, 6.25f * (fraction - 0.66f)));
            mPathList.add(pathWrapper);
          //長線條3
            Path longLine3 = provideLinePath(roundCorner, roundCorner * 6f, lineWidth);
            pathWrapper = new PathWrapper(longLine3, Math.min(1, 6.25f * (fraction - 0.82f)));
            mPathList.add(pathWrapper);
        }
    }

接下里就可以寫個(gè)按鈕不斷改變 fraction 來觀察繪制效果了

刷新過程

刷新的過程可以分為四中狀態(tài):


image
image
image

image

刷新過程顯示就是四中狀態(tài)圖形在一定時(shí)間間隔內(nèi)循環(huán)切換顯示
這部分就比較簡單了薪丁,確定好圖形直接繪制即可,這里貼出 第二個(gè)狀態(tài)的代碼

 class RefreshState2 extends State {


        @Override
        protected void initStatePath() {

            PathWrapper pathWrapper = new PathWrapper(roundPath, 1);
            mPathList.add(pathWrapper);


            Path rectPath = provideRectPath(contentWidth-roundCorner-rectWidth, roundCorner);
            pathWrapper = new RectPathWrapper(rectPath, 1);
            mPathList.add(pathWrapper);


            float shortLeft = roundCorner;
            Path shortLine1 = provideLinePath(shortLeft, roundCorner, shortLineWidth);
            pathWrapper = new RectPathWrapper(shortLine1, 1);
            mPathList.add(pathWrapper);


            Path shortLine2 = provideLinePath(shortLeft, roundCorner * 2f, shortLineWidth);
            pathWrapper = new PathWrapper(shortLine2, 1);
            mPathList.add(pathWrapper);
//

            Path shortLine3 = provideLinePath(shortLeft, roundCorner * 3f, shortLineWidth);
            pathWrapper = new PathWrapper(shortLine3, 1);
            mPathList.add(pathWrapper);
//
//
            Path longLine1 = provideLinePath(roundCorner, roundCorner * 4f, lineWidth);
            pathWrapper = new PathWrapper(longLine1, 1);
            mPathList.add(pathWrapper);
//
            Path longLine2 = provideLinePath(roundCorner, roundCorner * 5f, lineWidth);
            pathWrapper = new PathWrapper(longLine2, 1);
            mPathList.add(pathWrapper);
//
            Path longLine3 = provideLinePath(roundCorner, roundCorner * 6f, lineWidth);
            pathWrapper = new PathWrapper(longLine3, 1);
            mPathList.add(pathWrapper);
        }

    }

代碼比較簡單就是 計(jì)算坐標(biāo)馅精,創(chuàng)建Path 然后繪制交由公共的PathWrapper 完成
狀態(tài)的切換

public void setDragState() {
        if (mDragState instanceof DragState) {
            mDragState = new RefreshState1();
        } else if (mDragState instanceof RefreshState1) {
            mDragState = new RefreshState2();
        } else if (mDragState instanceof RefreshState2) {
            mDragState = new RefreshState3();
        } else if (mDragState instanceof RefreshState3) {
            mDragState = new RefreshState4();
        } else if (mDragState instanceof RefreshState4) {
            mDragState = new RefreshState1();
        }
        postInvalidate();
    }

結(jié)合下拉刷新動(dòng)起來

下拉刷新使用 SmartRefreshLayout严嗜,正如它的介紹所說 SmartRefreshLayout是一個(gè)“聰明”或者“智能”的下拉刷新布局,并且支持自定義多種Header洲敢,F(xiàn)ooter漫玄。自定義Header文檔說明

代碼直接貼出來

public class TodayNewsHeader extends LinearLayout implements RefreshHeader {

    public static String REFRESH_HEADER_PULLDOWN = "下拉推薦";
    public static String REFRESH_HEADER_REFRESHING = "推薦中...";
    public static String REFRESH_HEADER_RELEASE = "松開推薦";
    private NewRefreshView mNewRefreshView;
    private TextView releaseText;


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

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

    public TodayNewsHeader(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);
    }

    private void initView(Context context) {
        this.setGravity(Gravity.CENTER_HORIZONTAL);
        this.setOrientation(LinearLayout.VERTICAL);

        mNewRefreshView = new NewRefreshView(context);

        LinearLayout.LayoutParams lpNewRefresh = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        lpNewRefresh.setMargins(30, dip2px(context,30), 30, 0);

        this.addView(mNewRefreshView, lpNewRefresh);


        LinearLayout.LayoutParams lpReleaseText = new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
        lpReleaseText.setMargins(0, 30, 0, 30);

        releaseText = new TextView(context);
        releaseText.setText(REFRESH_HEADER_PULLDOWN);
        releaseText.setTextColor(0xff666666);
        addView(releaseText, lpReleaseText);
        
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            mNewRefreshView.setDragState();
            mHandler.sendEmptyMessageDelayed(0, 250);
        }
    };

    @NonNull
    @Override
    public View getView() {
        return this;
    }

    @NonNull
    @Override
    public SpinnerStyle getSpinnerStyle() {
        return SpinnerStyle.Translate;
    }

    @Override
    public void setPrimaryColors(int... colors) {

    }

    @Override
    public void onInitialized(@NonNull RefreshKernel kernel, int height, int extendHeight) {

    }

    @Override
    public void onPulling(float percent, int offset, int height, int extendHeight) {
        Log.e("TAG", "fraction:" + percent);
        mNewRefreshView.setFraction((percent - 0.8f) * 6f);
    }

    @Override
    public void onReleasing(float percent, int offset, int height, int extendHeight) {
        onPulling(percent, offset, height, extendHeight);
    }

    @Override
    public void onReleased(RefreshLayout refreshLayout, int height, int extendHeight) {
        mHandler.removeCallbacksAndMessages(null);
        mHandler.sendEmptyMessage(0);
    }

    @Override
    public void onStartAnimator(@NonNull RefreshLayout refreshLayout, int height, int extendHeight) {

    }

    @Override
    public int onFinish(@NonNull RefreshLayout refreshLayout, boolean success) {
        mHandler.removeCallbacksAndMessages(null);
        mNewRefreshView.setDrag();
        return 0;
    }

    @Override
    public void onHorizontalDrag(float percentX, int offsetX, int offsetMax) {

    }

    @Override
    public boolean isSupportHorizontalDrag() {
        return false;
    }

    @Override
    public void onStateChanged(RefreshLayout refreshLayout, RefreshState oldState, RefreshState newState) {
        switch (newState) {
            case None:
                break;
            case PullDownToRefresh:
                releaseText.setText(REFRESH_HEADER_PULLDOWN);
                break;
            case PullUpToLoad:
                break;
            case ReleaseToRefresh:
                releaseText.setText(REFRESH_HEADER_RELEASE);
                break;
            case Refreshing:
                releaseText.setText(REFRESH_HEADER_REFRESHING);
                break;
            case Loading:
                break;
        }
    }

    /**
     * 根據(jù)手機(jī)的分辨率從 dip 的單位 轉(zhuǎn)成為 px(像素)
     */
    public static int dip2px(Context context,float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mHandler.removeCallbacksAndMessages(null);
        mHandler = null;
    }
}
  • TodayNewsHeader繼承自 LinearLayout 在 initView() 方法中 創(chuàng)建 NewRefreshView 和下方顯示文字,并添加到自身中压彭。
  • 關(guān)于getSpinnerStyle() 方法說明睦优,參考官方說明

變換方式
Translate 平行移動(dòng) 特點(diǎn): 最常見,HeaderView高度不會(huì)改變壮不,
Scale 拉伸形變 特點(diǎn):在下拉和上彈(HeaderView高度改變)時(shí)候刨秆,會(huì)自動(dòng)觸發(fā)OnDraw事件
FixedFront 固定在前面 特點(diǎn):不會(huì)上下移動(dòng),HeaderView高度不會(huì)改變
FixedBehind 固定在后面 特點(diǎn):不會(huì)上下移動(dòng)忆畅,HeaderView高度不會(huì)改變(類似微信瀏覽器效果)
Screen 全屏幕 特點(diǎn):固定在前面,尺寸充滿整個(gè)布局

  • onPulling 與 onReleasoing 拖拽過程與下拉放回過程尸执,執(zhí)行 mNewRefreshView.setFraction();操作家凯,修改 繪制比例
  • onReleased 出發(fā)下拉刷新,開啟刷新動(dòng)畫如失,我們?cè)谏厦娣治鏊⑿逻^程是 四中狀態(tài)圖形在一定時(shí)間間隔內(nèi)循環(huán)切換顯示绊诲,這里我采用可Handler 的形式
 private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            mNewRefreshView.setDragState();
            mHandler.sendEmptyMessageDelayed(0, 250);
        }
    };
...
//使用handler 的好習(xí)慣,先清除消息再發(fā)送
  mHandler.removeCallbacksAndMessages(null);
        mHandler.sendEmptyMessage(0);

  • onFinish刷新完成會(huì)調(diào)用褪贵,返回值為 頭部延遲收回的時(shí)間 在這個(gè)方法里 需要清除 handler 并且重置 NewRefreshView 的狀態(tài)為拖拽狀態(tài)
  • onStateChanged方法 刷新狀態(tài)變化時(shí)回調(diào)掂之,在這里完成下方文本的切換顯示

項(xiàng)目地址 TodayNewsHeader

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市脆丁,隨后出現(xiàn)的幾起案子世舰,更是在濱河造成了極大的恐慌,老刑警劉巖槽卫,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件跟压,死亡現(xiàn)場離奇詭異,居然都是意外死亡歼培,警方通過查閱死者的電腦和手機(jī)震蒋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門茸塞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人查剖,你說我怎么就攤上這事钾虐。” “怎么了笋庄?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵效扫,是天一觀的道長。 經(jīng)常有香客問我无切,道長荡短,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任哆键,我火速辦了婚禮掘托,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘籍嘹。我一直安慰自己闪盔,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布辱士。 她就那樣靜靜地躺著泪掀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪颂碘。 梳的紋絲不亂的頭發(fā)上异赫,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音头岔,去河邊找鬼塔拳。 笑死,一個(gè)胖子當(dāng)著我的面吹牛峡竣,可吹牛的內(nèi)容都是我干的靠抑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼适掰,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼颂碧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起类浪,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤载城,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后费就,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體个曙,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了垦搬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呼寸。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖猴贰,靈堂內(nèi)的尸體忽然破棺而出对雪,到底是詐尸還是另有隱情,我是刑警寧澤米绕,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布瑟捣,位于F島的核電站,受9級(jí)特大地震影響栅干,放射性物質(zhì)發(fā)生泄漏迈套。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一碱鳞、第九天 我趴在偏房一處隱蔽的房頂上張望桑李。 院中可真熱鬧,春花似錦窿给、人聲如沸贵白。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽禁荒。三九已至,卻和暖如春角撞,著一層夾襖步出監(jiān)牢的瞬間呛伴,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來泰國打工谒所, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留磷蜀,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓百炬,卻偏偏與公主長得像,于是被迫代替她去往敵國和親污它。 傳聞我的和親對(duì)象是個(gè)殘疾皇子剖踊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,116評(píng)論 25 707
  • 1、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫組件 SD...
    陽明先生_X自主閱讀 15,980評(píng)論 3 119
  • 今天衫贬,背文《論語》: 仁者不憂德澈,知者不惑,勇者不懼固惯。 不怨天梆造,不尤人。下學(xué)而上達(dá)。
    孔玲外小閱讀 201評(píng)論 0 0
  • 1 心理傷害 頭痛醫(yī)頭镇辉,腳痛醫(yī)腳屡穗。情緒受傷時(shí)應(yīng)該怎么辦? 2 心理傷害“七宗罪” 拒絕——孤獨(dú)——喪失忽肛、創(chuàng)傷——內(nèi)...
    琳娜911閱讀 104評(píng)論 0 1
  • 有些事求不得別人的感同身受屹逛,你所看到的不痛不癢础废,無理由的歇斯底里或是黯然落淚,不會(huì)懂它背后的痛苦罕模,輾轉(zhuǎn)评腺,打碎了吞咽...
    藍(lán)湛的湛閱讀 197評(píng)論 2 1