何不自己動手去實現(xiàn)一個屬于自己的個性化Android下拉刷新庫粥诫?

如今油航,下拉刷新都已經成為App的標配了,哪個App會沒有下拉刷新呢怀浆?作為一個普通app用戶谊囚,想要去刷新內容,習慣性地就下拉一下执赡,已經成為用戶的一種習慣啦镰踏。作為一個開發(fā)者,想要集成下拉刷新沙合,直接就拷貝Android-PullToRefresh或者是android-Ultra-Pull-To-Refresh又或者其他下拉刷新庫奠伪,直接使用經典的下拉刷新UI,一個標志性的下拉箭頭首懈,一句經典的下拉以刷新更多绊率。一開始還好,慢慢的作為一個使用者而言究履,就覺得沒什么新意了滤否,作為一個開發(fā)者也覺得沒什么挑戰(zhàn)了。

那這樣挎袜,何不嘗試自己動手去實現(xiàn)一個真正屬于自己的下拉刷新庫呢顽聂?嘿嘿肥惭,那說干就干唄盯仪。那想想紊搪,現(xiàn)在下拉刷新的輪子那么多,我們也不可能從零開始寫全景,時間也不允許啊耀石,白天要上班寫業(yè)務代碼,回到宿舍還得重復別人寫過的代碼爸黄,而且自己寫的還派不上用場滞伟,因為已經有現(xiàn)成的,而且別人寫的東西那么多人用上了炕贵,踩過的坑肯定比你想的要多梆奈。雖然話說凡事要自己去實踐,理解的才會更深称开。說是這么說亩钟,但是我還是覺得站在巨人肩膀上,才會看得更遠鳖轰,嘿嘿......

正因為如此清酥,我才基于android-Ultra-Pull-To-Refresh實現(xiàn)一個很Q的笑臉下拉刷新,不吹不黑蕴侣,真的很Q哦焰轻。這個下拉大概的效果就是,下拉時昆雀,隨header高度變化而縮放辱志、轉眼睛,轉啊轉狞膘。松開時荸频,一個轉眼睛的笑臉加載動畫。

扯那么多客冈,我自己都覺得有點不耐煩了旭从。下面來簡要分析一下,怎么去實現(xiàn)一個個性化的下拉刷新庫场仲。以下是整個庫的目錄和悦,想不到吧,就僅僅三個類渠缕,一個布局文件鸽素。就可以實現(xiàn)你自己能想到的下拉效果。

Paste_Image.png

下面貼出最主要相關的類

  • PullToRefreshFaceView

/**
 *
 * @作 用:下拉刷新的笑臉
 * @創(chuàng) 建 人: linguoding
 * @日 期: 2016/3/9
 */
public class PullToRefreshFaceView extends View {
    private Paint paint;//畫筆
    private Paint eyePaint;
    private int backgroupColor;
    private int width;
    private int height;
    private int centerWidth;
    private int centerHeight;
    private float degrees;
    private float radius = 0;
    private float sweepRadius = 180;

    private int radiusCircle;
    private int eyeRadius;
    private int eyeBallRadius;
    private boolean isDrawFace = false;

    AnimatorSet set = new AnimatorSet();


    public PullToRefreshFaceView(Context context) {
        super(context);
        initView();
    }

    public PullToRefreshFaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.LoadingView);
        backgroupColor = array.getColor(R.styleable.LoadingView_backgroupColor, Color.BLACK);
        array.recycle();
        initView();

    }

    public void setDegrees(float degrees) {
        this.degrees = degrees;
        invalidate();
    }

    public void setRadius(float radius) {
        this.radius = radius;
        invalidate();
    }

    public void setSweepRadius(float sweepRadius) {
        this.sweepRadius = sweepRadius;
        invalidate();
    }

    public void setRadiusCircle(int radiusCircle) {
        this.radiusCircle = radiusCircle;
    }

    public void setEyeRadius(int eyeRadius) {
        this.eyeRadius = eyeRadius;

    }

    public void setEyeBallRadius(int eyeBallRadius) {
        this.eyeBallRadius = eyeBallRadius;

    }

    public void setDrawFace(boolean isDrawFace) {
        this.isDrawFace = isDrawFace;
    }

    public int getRadiusCircle() {
        return radiusCircle;
    }

    public int getEyeRadius() {
        return eyeRadius;
    }

    public int getEyeBallRadius() {
        return eyeBallRadius;
    }

    public boolean isDrawFace() {
        return isDrawFace;
    }

    public void setBackgroupColor(int backgroupColor) {
        this.backgroupColor = backgroupColor;
    }

    /**
     * 刷新用的效果
     *
     * @param sunRadius
     * @param per
     */
    public void setPerView(int sunRadius, float per) {
        if (per >= 0.5) {
            isDrawFace = true;
        } else {
            isDrawFace = false;
        }
        per = Math.min(per, 1);
        float tempRadius = sunRadius * per;
        this.radiusCircle = (int) tempRadius;
        invalidate();
    }





    private void initView() {
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(backgroupColor);
        //眼眶畫筆
        eyePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        eyePaint.setColor(Color.WHITE);
        eyePaint.setStyle(Paint.Style.FILL);
        createAnimatorSet();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        /*super.onMeasure(widthMeasureSpec, heightMeasureSpec);*/
        width = measureResult(widthMeasureSpec);
        height = measureResult(heightMeasureSpec);
        centerWidth = width >> 1;
        centerHeight = height >> 1;
        setMeasuredDimension(width, height);

    }

    private int measureResult(int widthMeasureSpec) {
        int result = 0;
        int sizeSpec = MeasureSpec.getSize(widthMeasureSpec);
        int modeSpec = MeasureSpec.getMode(widthMeasureSpec);
        if (modeSpec == MeasureSpec.EXACTLY) {
            result = sizeSpec;
        } else {
            result = 400;
            if (modeSpec == MeasureSpec.AT_MOST) {
                result = Math.min(result, sizeSpec);
            }
        }
        return result;
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        centerWidth = width / 2;
        centerHeight = height / 2;
        canvas.translate(centerWidth, centerHeight);
        radiusCircle = Math.min(centerWidth, centerHeight);
        //畫圓
        canvas.drawCircle(0, 0, radiusCircle, paint);
        if (isDrawFace) {
            //畫兩個眼框
            eyeRadius = Math.min(centerWidth / 3, centerHeight / 3);
            canvas.drawCircle(-centerWidth / 2, -centerHeight >> 3, eyeRadius, eyePaint);
            canvas.drawCircle(centerWidth / 2, -centerHeight >> 3, eyeRadius, eyePaint);
            //畫嘴巴
            canvas.drawArc(new RectF(-eyeRadius, 0, eyeRadius, eyeRadius * 2), 0, 180, true, eyePaint);

            canvas.save();
            //畫兩個眼睛
            eyeBallRadius = Math.min(centerWidth >> 3, centerHeight >> 3);
            canvas.translate(-centerWidth / 2, -centerHeight >> 3);
            canvas.rotate(-degrees);
            canvas.drawCircle(0, (eyeRadius >> 1), eyeBallRadius, paint);
            canvas.restore();

            canvas.save();

            canvas.translate(centerWidth / 2, -centerHeight >> 3);
            canvas.rotate(-degrees);
            canvas.drawCircle(0, (eyeRadius >> 1), eyeBallRadius, paint);
            canvas.restore();

            //畫兩個眼皮
            canvas.save();
            canvas.translate(-centerWidth / 2, -centerHeight >> 3);
            canvas.drawArc(new RectF(-eyeRadius, -eyeRadius, eyeRadius, eyeRadius), -this.radius, -this.sweepRadius, false, paint);
            canvas.restore();

            canvas.save();
            canvas.translate(centerWidth / 2, -centerHeight >> 3);
            canvas.drawArc(new RectF(-eyeRadius, -eyeRadius, eyeRadius, eyeRadius), -this.radius, -this.sweepRadius, false, paint);
            canvas.restore();
        }


    }

    private void createAnimatorSet() {
        ValueAnimator rotateAnimator = ValueAnimator.ofFloat(0, 360).setDuration(3000);
        rotateAnimator.setInterpolator(new LinearInterpolator());
        rotateAnimator.setRepeatCount(-1);
        rotateAnimator.setEvaluator(new FloatEvaluator());
        rotateAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                degrees = (float) animation.getAnimatedValue();
                postInvalidate();
            }
        });

        ValueAnimator translationAnimator = ValueAnimator.ofFloat(0, 90, 0).setDuration(3000);
        translationAnimator.setInterpolator(new LinearInterpolator());
        translationAnimator.setRepeatCount(-1);
        translationAnimator.setEvaluator(new FloatEvaluator());
        translationAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                radius = (float) animation.getAnimatedValue();
                postInvalidate();
            }
        });

        ValueAnimator sweepAnimator = ValueAnimator.ofFloat(180, 0, 180).setDuration(3000);
        sweepAnimator.setInterpolator(new LinearInterpolator());
        sweepAnimator.setRepeatCount(-1);
        sweepAnimator.setEvaluator(new FloatEvaluator());
        sweepAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                sweepRadius = (float) animation.getAnimatedValue();
                postInvalidate();
            }
        });
        set.playTogether(rotateAnimator, translationAnimator, sweepAnimator);
    }

    public void startAnimators() {
        set.start();
    }

    public void stopAnimators() {
        set.cancel();
    }
}

  • FacePullToRefreshHeader 類
package com.pulltorefreshlibrary;

import android.content.Context;
import android.content.SharedPreferences;
import android.support.v4.view.ViewCompat;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;

import com.pulltorefreshlibrary.view.PullToRefreshFaceView;

import java.text.SimpleDateFormat;
import java.util.Date;

import in.srain.cube.views.ptr.PtrFrameLayout;
import in.srain.cube.views.ptr.PtrUIHandler;
import in.srain.cube.views.ptr.indicator.PtrIndicator;

public class FacePullToRefreshHeader extends FrameLayout implements PtrUIHandler {
    private final static String KEY_SharedPreferences = "face_ptr_classic_last_update";
    private TextView mTitleTextView;
    private PullToRefreshFaceView mLoadView;
    private long mLastUpdateTime = -1;
    private TextView mLastUpdateTextView;
    private String mLastUpdateTimeKey;
    private static SimpleDateFormat sDataFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private boolean mShouldShowLastUpdate;

    private LastUpdateTimeUpdater mLastUpdateTimeUpdater = new LastUpdateTimeUpdater();


    public FacePullToRefreshHeader(Context context) {
        super(context);
        initViews(null);
    }

    public FacePullToRefreshHeader(Context context, AttributeSet attrs) {
        super(context, attrs);
        initViews(attrs);
    }

    public FacePullToRefreshHeader(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initViews(attrs);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mLastUpdateTimeUpdater != null) {
            mLastUpdateTimeUpdater.stop();
        }
    }

    private void initViews(AttributeSet attrs) {
        View header = LayoutInflater.from(getContext()).inflate(R.layout.face_pull_to_refresh_header, this);
        mTitleTextView = (TextView) header.findViewById(R.id.ptr_face_header_title);
        mLastUpdateTextView = (TextView) header.findViewById(R.id.ptr_face_header_last_update);
        mLoadView = (PullToRefreshFaceView) header.findViewById(R.id.ptr_load_view);

    }


    private void tryUpdateLastUpdateTime() {
        if (TextUtils.isEmpty(mLastUpdateTimeKey) || !mShouldShowLastUpdate) {
            mLastUpdateTextView.setVisibility(GONE);
        } else {
            String time = getLastUpdateTime();
            if (TextUtils.isEmpty(time)) {
                mLastUpdateTextView.setVisibility(GONE);
            } else {
                mLastUpdateTextView.setVisibility(VISIBLE);
                mLastUpdateTextView.setText(time);
            }
        }
    }


    public void setLastUpdateTimeKey(String key) {
        if (TextUtils.isEmpty(key)) {
            return;
        }
        mLastUpdateTimeKey = key;
    }

    public void setLastUpdateTimeRelateObject(Object object) {
        setLastUpdateTimeKey(object.getClass().getName());
    }

    
     /**
     * 得到最后刷新時間
     *
     * @return
     */
    private String getLastUpdateTime() {

        if (mLastUpdateTime == -1 && !TextUtils.isEmpty(mLastUpdateTimeKey)) {
            mLastUpdateTime = getContext().getSharedPreferences(KEY_SharedPreferences, 0).getLong(mLastUpdateTimeKey, -1);
        }
        if (mLastUpdateTime == -1) {
            return null;
        }
        long diffTime = new Date().getTime() - mLastUpdateTime;
        int seconds = (int) (diffTime / 1000);
        if (diffTime < 0) {
            return null;
        }
        if (seconds <= 0) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        sb.append(getContext().getString(R.string.ai_jia_ptr_last_update));

        if (seconds < 60) {
            sb.append(seconds + getContext().getString(in.srain.cube.views.ptr.R.string.cube_ptr_seconds_ago));
        } else {
            int minutes = (seconds / 60);
            if (minutes > 60) {
                int hours = minutes / 60;
                if (hours > 24) {
                    Date date = new Date(mLastUpdateTime);
                    sb.append(sDataFormat.format(date));
                } else {
                    sb.append(hours + getContext().getString(R.string.ai_jia_ptr_hours_ago));
                }

            } else {
                sb.append(minutes + getContext().getString(R.string.ai_jia_ptr_minutes_ago));
            }
        }
        return sb.toString();
    }

    private void resetView() {
        //隱藏加載view和停止動畫
        mLoadView.stopAnimators();
        mLoadView.setVisibility(INVISIBLE);

    }


    /**
     * 重置亦鳞,回到頂部的
     *
     * @param frame
     */
    @Override
    public void onUIReset(PtrFrameLayout frame) {
        resetView();
        mShouldShowLastUpdate = true;
        tryUpdateLastUpdateTime();
    }


    /**
     * 準備刷新馍忽,Header 將要出現(xiàn)時調用棒坏。
     *
     * @param frame
     */
    @Override
    public void onUIRefreshPrepare(PtrFrameLayout frame) {
        mShouldShowLastUpdate = true;
        tryUpdateLastUpdateTime();
        mLoadView.setVisibility(VISIBLE);
        mTitleTextView.setVisibility(VISIBLE);
        mTitleTextView.setText(getResources().getString(R.string.ai_jia_ptr_pull_down_to_refresh));

    }

    /**
     * 開始刷新,Header 進入刷新狀態(tài)之前調用遭笋。
     *
     * @param frame
     */
    @Override
    public void onUIRefreshBegin(PtrFrameLayout frame) {
        mShouldShowLastUpdate = false;

        /**
         * 讓loadView開始動畫
         * */
        mLoadView.startAnimators();
        mTitleTextView.setVisibility(VISIBLE);
        mTitleTextView.setText(R.string.ai_jia_ptr_refreshing);
        tryUpdateLastUpdateTime();
        mLastUpdateTimeUpdater.stop();
    }

    @Override
    public void onUIRefreshComplete(PtrFrameLayout frame) {
        /*hideRotateView();
        mProgressBar.setVisibility(INVISIBLE);*/
        /*
         * 加載完成坝冕,loadView停止動畫
         * */
        mLoadView.stopAnimators();
        mTitleTextView.setVisibility(VISIBLE);
        mTitleTextView.setText(getResources().getString(R.string.ai_jia_ptr_refresh_complete));

        // update last update time
        SharedPreferences sharedPreferences = getContext().getSharedPreferences(KEY_SharedPreferences, 0);
        if (!TextUtils.isEmpty(mLastUpdateTimeKey)) {
            mLastUpdateTime = new Date().getTime();
            sharedPreferences.edit().putLong(mLastUpdateTimeKey, mLastUpdateTime).commit();
        }
    }


    /**
     * 下拉過程中位置變化回調。
     *
     * @param frame
     * @param isUnderTouch
     * @param status
     * @param ptrIndicator
     */
    @Override
    public void onUIPositionChange(PtrFrameLayout frame, boolean isUnderTouch, byte status, PtrIndicator ptrIndicator) {
        float percent = Math.min(1f, ptrIndicator.getCurrentPercent());//得到下拉過程的位置比例
        if (status == PtrFrameLayout.PTR_STATUS_PREPARE) {
            mLoadView.setDegrees(percent * 360 * 4);
            ViewCompat.setScaleX(mLoadView, percent);
            ViewCompat.setScaleY(mLoadView, percent);
            mLoadView.setEyeRadius((int) (mLoadView.getEyeRadius()*percent));
            mLoadView.setEyeBallRadius((int) (mLoadView.getEyeBallRadius()*percent));
            mLoadView.setPerView(mLoadView.getRadiusCircle(), percent);
            if (percent < 0.5) {
                mLoadView.setRadius((percent * 180));
                mLoadView.setSweepRadius((180 - percent * 360));
            } else {
                percent = (float) (percent - 0.5);
                mLoadView.setRadius((90 - percent * 180));
                mLoadView.setSweepRadius((percent * 360));
            }

        }
        final int mOffsetToRefresh = frame.getOffsetToRefresh();
        final int currentPos = ptrIndicator.getCurrentPosY();//當前位置
        final int lastPos = ptrIndicator.getLastPosY();//上一個位置
        if (currentPos < mOffsetToRefresh && lastPos >= mOffsetToRefresh) {
            if (isUnderTouch && status == PtrFrameLayout.PTR_STATUS_PREPARE) {
                //下拉刷新
                crossRotateLineFromBottomUnderTouch(frame);

            }
        } else if (currentPos > mOffsetToRefresh && lastPos <= mOffsetToRefresh) {
            if (isUnderTouch && status == PtrFrameLayout.PTR_STATUS_PREPARE) {
                //釋放刷新
                crossRotateLineFromTopUnderTouch(frame);

            }
        }
    }


    /**
     * 釋放刷新
     *
     * @param frame
     */
    private void crossRotateLineFromTopUnderTouch(PtrFrameLayout frame) {
        if (!frame.isPullToRefresh()) {
            mTitleTextView.setVisibility(VISIBLE);
            mTitleTextView.setText(R.string.ai_jia_ptr_release_to_refresh);
        }
    }

    /**
     * 下拉刷新
     *
     * @param frame
     */
    private void crossRotateLineFromBottomUnderTouch(PtrFrameLayout frame) {
        mTitleTextView.setVisibility(VISIBLE);
        if (frame.isPullToRefresh()) {
            mTitleTextView.setText(getResources().getString(R.string.ai_jia_ptr_pull_down_to_refresh));
        } else {
            mTitleTextView.setText(getResources().getString(R.string.ai_jia_ptr_pull_down_to_refresh));
        }
    }


    private class LastUpdateTimeUpdater implements Runnable {
        private boolean mRunning = false;

        private void start() {
            if (TextUtils.isEmpty(mLastUpdateTimeKey)) {
                return;
            }
            mRunning = true;
            run();
        }

        private void stop() {
            mRunning = false;
            removeCallbacks(this);
        }

        @Override
        public void run() {
            tryUpdateLastUpdateTime();
            if (mRunning) {
                postDelayed(this, 1000);
            }
        }
    }
}
  • FacePullToRefreshLayout


public class FacePullToRefreshLayout extends PtrFrameLayout {
    private FacePullToRefreshHeader mPullToRefreshHeader;
    private RefreshListener refreshListener;

    public FacePullToRefreshLayout(Context context) {
        super(context);
        initViews();
    }

    public FacePullToRefreshLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        initViews();
    }

    public FacePullToRefreshLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initViews();
    }

    private void initViews() {
        mPullToRefreshHeader = new FacePullToRefreshHeader(getContext());
        setHeaderView(mPullToRefreshHeader);
        addPtrUIHandler(mPullToRefreshHeader);
        setPtrHandler(new PtrDefaultHandler() {
            @Override
            public void onRefreshBegin(PtrFrameLayout frame) {
                if (refreshListener != null) {
                    refreshListener.onRefresh(frame);
                }
            }
        });
    }

    public FacePullToRefreshHeader getHeader() {
        return mPullToRefreshHeader;
    }

    public void setLastUpdateTimeKey(String key) {
        if (mPullToRefreshHeader != null) {
            mPullToRefreshHeader.setLastUpdateTimeKey(key);
        }
    }


    public void setLastUpdateTimeRelateObject(Object object) {
        if (mPullToRefreshHeader != null) {
            mPullToRefreshHeader.setLastUpdateTimeRelateObject(object);
        }
    }


    public interface RefreshListener {
        void onRefresh(PtrFrameLayout frame);
    }

    public void setRefreshListener(RefreshListener refreshListener) {
        this.refreshListener = refreshListener;
    }
}

  • 布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:layout_width="match_parent"
              android:layout_height="90dp"
              android:gravity="center"
              android:orientation="vertical">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="vertical">

            <com.pulltorefreshlibrary.view.PullToRefreshFaceView
                android:id="@+id/ptr_load_view"
                android:layout_width="50dp"
                android:layout_height="50dp"
                app:backgroupColor="#88c6c6c6"
                />

            <TextView
                android:id="@+id/ptr_face_header_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="下拉刷新..."
                android:textColor="#666666"
                android:textSize="12sp"/>

        </LinearLayout>

        <TextView
            android:id="@+id/ptr_face_header_last_update"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="2dp"
            android:text="距離上次刷新:08秒之前"
            android:textColor="#999999"
            android:textSize="10sp"/>
    </LinearLayout>


</LinearLayout>

想想瓦呼,還是放張圖片喂窟,比較有吸引力。

Paste_Image.png

好啦央串,就到此為止吧磨澡,代碼不難,注釋寫得也清楚质和,所以就不說明了哈稳摄。主要還是因為我懶,以后再慢慢試著寫點分析饲宿,自己的思路什么的厦酬。最后,源碼放在Github上褒傅,覺得可以學到點東西的弃锐,start一下吧!點我殿托,點我吧

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末霹菊,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子支竹,更是在濱河造成了極大的恐慌旋廷,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件礼搁,死亡現(xiàn)場離奇詭異饶碘,居然都是意外死亡,警方通過查閱死者的電腦和手機馒吴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門扎运,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人饮戳,你說我怎么就攤上這事豪治。” “怎么了扯罐?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵负拟,是天一觀的道長。 經常有香客問我歹河,道長掩浙,這世上最難降的妖魔是什么花吟? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮厨姚,結果婚禮上衅澈,老公的妹妹穿的比我還像新娘。我一直安慰自己遣蚀,他們只是感情好矾麻,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布纱耻。 她就那樣靜靜地躺著芭梯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪弄喘。 梳的紋絲不亂的頭發(fā)上玖喘,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天洒闸,我揣著相機與錄音躏碳,去河邊找鬼。 笑死彻桃,一個胖子當著我的面吹牛急但,可吹牛的內容都是我干的澎媒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼波桩,長吁一口氣:“原來是場噩夢啊……” “哼戒努!你這毒婦竟也來了?” 一聲冷哼從身側響起镐躲,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤储玫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后萤皂,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體撒穷,經...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年裆熙,在試婚紗的時候發(fā)現(xiàn)自己被綠了端礼。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡入录,死狀恐怖蛤奥,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情纷跛,我是刑警寧澤喻括,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站贫奠,受9級特大地震影響唬血,放射性物質發(fā)生泄漏望蜡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一拷恨、第九天 我趴在偏房一處隱蔽的房頂上張望脖律。 院中可真熱鬧,春花似錦腕侄、人聲如沸小泉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽微姊。三九已至,卻和暖如春分预,著一層夾襖步出監(jiān)牢的瞬間兢交,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工笼痹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留配喳,地道東北人。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓凳干,卻偏偏與公主長得像晴裹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子救赐,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,284評論 25 707
  • 內容抽屜菜單ListViewWebViewSwitchButton按鈕點贊按鈕進度條TabLayout圖標下拉刷新...
    皇小弟閱讀 46,791評論 22 665
  • 初戀净响,滿天星辰最亮的一顆 文/純梅子 當接到多年沒聯(lián)系的恩師——中學班主任打來電話少欺,邀我回老家參加同學小聚時,我驚...
    純梅子閱讀 290評論 2 3
  • 畢業(yè)馋贤,離別赞别,散伙飯,那些我們在流火的七月里小心翼翼想要掩藏的脆弱與不舍總會適時地出賣我們:原來我并不想離開配乓,你...
    擁字取暖閱讀 308評論 0 0
  • 妝前:將保濕型化妝水換成美白化妝水 保濕精華液 太油的話 oil free 防曬 眼仿滔、臉卸妝分開做 油水分離型眼唇...
    伊依Yoyko閱讀 222評論 0 0