Android存储密码项目备忘录

好吧这一段时间确实没有好好的敲代码了,深深的罪恶感啊,准备这周搞一下在guihub上看到的一个密码应用PassWord,准备把这个仿写完成的,主要为了熟悉一些现在热门但在现在公司项目上用不到的东东.

知识点 |

  1. Android手势解锁 |
  2. Realm数据库的使用 |
  3. MVP架构的搭建 |
  4. 一些5.0的控件使用 |
  5. 自定义控件 |

1.Android手势解锁


昨天看了一下鸿洋之前写的手势解锁控件的实现,膜拜一下,感觉自己的代码量太少需要大大加强啊.好了废话不多说了,直接看实现,这里主要就是自定义view和画图两个方面的东东.

整个解锁的界面构成包括两个部分,解锁的圆,以及手指划过时的线两个部分,圆的构成包括两个部分外圈的空心圆以及内圈的实心圆,然后圆的状态包括三个部分正常未按下,按下,手指抬起主要是颜色的变化.

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;

/**
 * 手势解锁中单个圆的view
 * Created by apple on 16/6/20.
 */
    public class GestureLockView extends View {
    private static final String TAG = "GestureLockView";

    //触摸点的三种状态
    enum Mode {
        STATUS_NO_FINGER, STATUS_FINGER_ON, STATUS_FINGER_UP;
    }

    //初始状态
    private Mode mCurrentStatus = Mode.STATUS_NO_FINGER;
    //圆的宽高
    private int mWidth;
    private int mHeight;
    //圆的半径
    private int mRadius;
    //画笔的宽度
    private int mStrokeWidth = 2;
    //圆的中心坐标点
    private int mCenterX, mCenterY;
    private Paint mPaint;

    /**
     * 箭头(小三角最长边的一半长度 = mArrawRate * mWidth / 2 )
     */
    private float mArrowRate = 0.333f;
    private int mArrowDegree = -1;
    private Path mArrowPath;
    /**
     * 内圆的半径 = mInnerCircleRadiusRate * mRadus
     */
    private float mInnerCircleRadiusRate = 0.3F;

    /**
     * 四个颜色,可由用户自定义,初始化时由GestureLockViewGroup传入
     */
    private int mColorNoFingerInner;
    private int mColorNoFingerOutter;
    private int mColorFingerOn;
    private int mColorFingerUp;

    public GestureLockView(Context context) {
        super(context);
    }

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

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

    public GestureLockView(Context context, int colorNoFingerInner, int colorNoFingerOutter, int colorFingerOn, int colorFingerUp) {
        super(context);
        mColorFingerOn = colorFingerOn;
        mColorFingerUp = colorFingerUp;
        mColorNoFingerInner = colorNoFingerInner;
        mColorNoFingerOutter = colorNoFingerOutter;
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        //path 一个路径类
        mArrowPath = new Path();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = MeasureSpec.getSize(widthMeasureSpec);
        mHeight = MeasureSpec.getSize(heightMeasureSpec);
        //圆的边框为正方形,取两个最小的
        mWidth = mWidth < mHeight ? mWidth : mHeight;
        //获取圆的半径和圆点坐标
        mRadius = mCenterX = mCenterY = mWidth / 2;
        //减去画笔的宽度
        mRadius -= mStrokeWidth;
        //默认的三角位置为圆的正上方向上的剪头,然后根据两个GestureLockView来进行角度的旋转
        //确定位置以及确定圆的path路径
        float mArrowLength = mWidth / 2 * mArrowRate;
        mArrowPath.moveTo(mWidth / 2, mStrokeWidth + 2);//移动到线的起始点
        mArrowPath.lineTo(mWidth / 2 - mArrowLength, mStrokeWidth + mArrowLength + 2);//从原点到这个点划线
        mArrowPath.lineTo(mWidth / 2 + mArrowLength, mStrokeWidth + mArrowLength + 2);
        mArrowPath.close();
        mArrowPath.setFillType(Path.FillType.WINDING);//设置填充类型
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //根据不同的状态画圆
        switch (mCurrentStatus) {
            case STATUS_FINGER_ON:
                //按下时画圆
                //绘制外圆
                mPaint.setColor(mColorFingerOn);
                mPaint.setStyle(Paint.Style.STROKE);//只有边线
                mPaint.setStrokeWidth(2);
                canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
                //绘制内圆
                mPaint.setStyle(Paint.Style.FILL);
                canvas.drawCircle(mCenterX, mCenterY, mRadius * mInnerCircleRadiusRate, mPaint);
                break;
            case STATUS_FINGER_UP:
                //手指抬起时
                mPaint.setColor(mColorFingerUp);
                mPaint.setStyle(Paint.Style.STROKE);
                mPaint.setStrokeWidth(2);
                canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
                mPaint.setStyle(Paint.Style.FILL);
                canvas.drawCircle(mCenterX, mCenterY, mRadius * mInnerCircleRadiusRate, mPaint);
                drawArrow(canvas);
                break;
            case STATUS_NO_FINGER:
                //没有按下的状态
                //绘制外圆
                mPaint.setStyle(Paint.Style.FILL);//完全填充
                mPaint.setColor(mColorNoFingerOutter);
                canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
                //绘制内圆
                mPaint.setColor(mColorNoFingerInner);
                canvas.drawCircle(mCenterX, mCenterY, mRadius * mInnerCircleRadiusRate, mPaint);
                break;
        }
    }

    /**
     * 绘制剪头
     * canvas的save和restore的作用
     * 这两个是成对出现的 save 可以保存当前canvas上以有的状态
     * 一般我们需要是对某个特定元素进行旋转等操作,而这个操作又不想对其他的元素有影响,那么就可以使用这个
     * restore就可以取出之前保存的状态
     */
    private void drawArrow(Canvas canvas){
        if(mArrowDegree != -1){
            mPaint.setStyle(Paint.Style.FILL);
            canvas.save();
            canvas.rotate(mArrowDegree,mCenterX,mCenterY);//画布旋转
            canvas.drawPath(mArrowPath,mPaint);//绘制路径,这里其实绘制两条线,不过因为画笔模式为完全填充,所以就构建成了一个三角形
            canvas.restore();
        }
    }

    /**
     * 设置当前的模式并进行重新绘制
     */
    public void setMode(Mode mode){
        mCurrentStatus = mode;
        invalidate();
    }

    /**
     * 设置剪头的角度
     * @param degree
     */
    public void setmArrowDegree(int degree){
        mArrowDegree = degree;
    }

    public int getmArrowDegree(){
        return mArrowDegree;
    }
 }

然后是整体的布局,这里使用了自定义熟悉来设置一些参数,包括上面的颜色以及每行的个数,这里每行的个数和列是相互对应的,就是3*3,然后还有重试次数.自定义属性


import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.RelativeLayout;

import java.util.ArrayList;
import java.util.List;


/**
 * 抄的洪洋的手势解锁,这里有一个问题就是图像最开始的一个坐标点是从0开始的
 * Created by apple on 16/6/20.
 */
public class GestureLockViewGroup extends RelativeLayout {

    private static final String TAG = "GestureLockViewGroup";
    //所有的点view
    private GestureLockView[] mGestureLockViews;

    private int mCount = 4;
    //答案
    private int[] mAnswer = {1, 2,3, 6, 7};
    //被选中的图像id
    private List<Integer> mChoose = new ArrayList<>();
    private Paint mPaint;
    /**
     * 每个GestureLockView中间的间距 设置为:mGestureLockViewWidth * 25%
     */
    private int mMarginBetweenLockView = 30;
    /**
     * GestureLockView的边长 4 * mWidth / ( 5 * mCount + 1 )
     */
    private int mGestureLockViewWidth;

    /**
     * GestureLockView无手指触摸的状态下内圆的颜色
     */
    private int mNoFingerInnerCircleColor = 0xFF939090;
    /**
     * GestureLockView无手指触摸的状态下外圆的颜色
     */
    private int mNoFingerOuterCircleColor = 0xFFE0DBDB;
    /**
     * GestureLockView手指触摸的状态下内圆和外圆的颜色
     */
    private int mFingerOnColor = 0xFF378FC9;
    /**
     * GestureLockView手指抬起的状态下内圆和外圆的颜色
     */
    private int mFingerUpColor = 0xFFFF0000;

    /**
     * 宽度
     */
    private int mWidth;
    /**
     * 高度
     */
    private int mHeight;

    private Path mPath;
    /**
     * 指引线的开始位置x
     */
    private int mLastPathX;
    /**
     * 指引线的开始位置y
     */
    private int mLastPathY;
    /**
     * 指引下的结束位置
     */
    private Point mTmpTarget = new Point();

    /**
     * 最大尝试次数
     */
    private int mTryTimes = 4;
    /**
     * 回调接口
     */
    private OnGestureLockViewListener mOnGestureLockViewListener;

    public GestureLockViewGroup(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public GestureLockViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //获取自定义属性的值
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.GestureLockViewGroup, defStyleAttr, 0);

        int count = typedArray.getIndexCount();
        for (int a = 0; a < count; a++) {
            int index = typedArray.getIndex(a);
            switch (index) {
                case R.styleable.GestureLockViewGroup_color_finger_on:
                    mFingerOnColor = typedArray.getColor(a, mFingerOnColor);
                    break;
                case R.styleable.GestureLockViewGroup_color_finger_up:
                    mFingerUpColor = typedArray.getColor(a, mFingerUpColor);
                    break;
                case R.styleable.GestureLockViewGroup_color_no_finger_inner_circle:
                    mNoFingerInnerCircleColor = typedArray.getColor(a, mNoFingerInnerCircleColor);
                    break;
                case R.styleable.GestureLockViewGroup_color_no_finger_outer_circle:
                    mNoFingerOuterCircleColor = typedArray.getColor(a, mNoFingerOuterCircleColor);
                    break;
                case R.styleable.GestureLockViewGroup_count:
                    mCount = typedArray.getInteger(a, count);
                    break;
                case R.styleable.GestureLockViewGroup_tryTimes:
                    mTryTimes = typedArray.getInteger(a, mTryTimes);
                    break;
            }

        }
        typedArray.recycle();
        //初始化画笔

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPath = new Path();
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = MeasureSpec.getSize(widthMeasureSpec);
        mHeight = MeasureSpec.getSize(heightMeasureSpec);
        mHeight = mWidth = mWidth < mHeight ? mWidth : mHeight;
        //测量布局每个GestureLockView
        if (mGestureLockViews == null) {
            mGestureLockViews = new GestureLockView[mCount * mCount];
            // 这里鸿神说是根据屏幕宽度进行百分比的布局..计算方法没看懂
            // 计算每个GestureLockView的宽度
            mGestureLockViewWidth = (int) (4 * mWidth * 1.0f / (5 * mCount + 1));
            //计算每个GestureLockView的间距
            mMarginBetweenLockView = (int) (mGestureLockViewWidth * 0.25);
            // 设置画笔的宽度为GestureLockView的内圆直径稍微小点(不喜欢的话,随便设)
            mPaint.setStrokeWidth(mGestureLockViewWidth * 0.29f);
            for (int i = 0; i < mGestureLockViews.length; i++) {
                mGestureLockViews[i] = new GestureLockView(getContext(), mNoFingerInnerCircleColor, mNoFingerOuterCircleColor, mFingerOnColor, mFingerUpColor);
                mGestureLockViews[i].setId(i + 1);
                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(mGestureLockViewWidth, mGestureLockViewWidth);
                // 不是每行的第一个,则设置位置为前一个的右边
                if (i % mCount != 0) {
                    params.addRule(RelativeLayout.RIGHT_OF, mGestureLockViews[i - 1].getId());
                }
                // 从第二行开始,设置为上一行同一位置View的下面
                if (i > mCount - 1) {
                    params.addRule(RelativeLayout.BELOW, mGestureLockViews[i - mCount].getId());
                }
                //设置右下左上的边距
                int rightMargin = mMarginBetweenLockView;
                int bootomMargin = mMarginBetweenLockView;
                int leftMargin = 0;
                int topMargin = 0;
                //第一行有topMargin 第一列有leftMargin
                if (i >= 0 && i < mCount) {
                    topMargin = mMarginBetweenLockView;
                }

                if (i % mCount == 0) {
                    leftMargin = mMarginBetweenLockView;
                }
                params.setMargins(leftMargin, topMargin, rightMargin, bootomMargin);
                mGestureLockViews[i].setMode(GestureLockView.Mode.STATUS_NO_FINGER);
                addView(mGestureLockViews[i], params);
            }
        }
    }

    //这里就是处理手指滑动
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                    //手指按下的时候现把所有的重置
                reSet();
                break;
            case MotionEvent.ACTION_UP:
                //手指抬起的时候要进行剪头角度的测量和绘制,以及判断结果的正确与否
                mPaint.setColor(mFingerUpColor);
                mPaint.setAlpha(50);
                this.mTryTimes--;
                if (mOnGestureLockViewListener != null && mChoose.size() > 0) {
                    mOnGestureLockViewListener.onGestureEvent(checkAnswer());
                    if (mTryTimes <= 0) {
                        mOnGestureLockViewListener.onUnmatchedExceedBoundary();
                    }
                }
                //将终点设置为起点
                mTmpTarget.x = mLastPathX;
                mTmpTarget.y = mLastPathY;
                changeItemMode();
                for (int i = 0; i + 1 < mChoose.size(); i++) {
                    int startId = mChoose.get(i);
                    int nextId = mChoose.get(i + 1);
                    GestureLockView startView = (GestureLockView) findViewById(startId);
                    GestureLockView nextView = (GestureLockView) findViewById(nextId);
                    int dx = nextView.getLeft() - startView.getLeft();
                    int dy = nextView.getTop() - startView.getTop();
                    int degrees = (int) (Math.toDegrees(Math.atan2(dy, dx)) + 90);//角度的计算方法
                    startView.setmArrowDegree(degrees);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                mPaint.setColor(mFingerOnColor);
                mPaint.setAlpha(50);
                GestureLockView gestureLockView = getChildIdByPos(x, y);
                if (gestureLockView != null) {
                    int id = gestureLockView.getId();
                    if (!mChoose.contains(id)) {
                        mChoose.add(id);
                        gestureLockView.setMode(GestureLockView.Mode.STATUS_FINGER_ON);
                        if (mOnGestureLockViewListener != null) {
                            mOnGestureLockViewListener.onBlockSelected(id);
                        }
                        //设置划线的起点
                        mLastPathX = gestureLockView.getLeft() / 2 + gestureLockView.getRight() / 2;
                        mLastPathY = gestureLockView.getTop() / 2 + gestureLockView.getBottom() / 2;
                        if (mChoose.size() == 1) {
                            mPath.moveTo(mLastPathX, mLastPathY);
                        } else {
                            mPath.lineTo(mLastPathX, mLastPathY);
                        }

                    }
                }
                mTmpTarget.x = x;
                mTmpTarget.y = y;
                break;
        }
        invalidate();
        return true;
    }

    /**
     * 恢复初始设置
     */
    private void reSet() {
        mChoose.clear();
        mPath.reset();
        for (GestureLockView gestureLockView : mGestureLockViews) {
            gestureLockView.setMode(GestureLockView.Mode.STATUS_NO_FINGER);
            gestureLockView.setmArrowDegree(-1);
        }
    }
    //检测答案
    private boolean checkAnswer() {
        if (mAnswer.length != mChoose.size()) {
            Log.e(TAG,mAnswer.length+"length");
            return false;
        }
        for (int i = 0; i < mAnswer.length; i++) {
            Log.e(TAG,mChoose.get(i)+"point"+mAnswer[i]+"answer");
            if (mAnswer[i] != mChoose.get(i)) {
                return false;
            }
        }
        return true;
    }


    /**
     * 判断当前点是否在当前view中
     *
     * @param gestureLockView
     * @param x
     * @param y
     * @return
     */
    private boolean checkPositionInChild(GestureLockView gestureLockView, int x, int y) {
        int padding = (int) (mGestureLockViewWidth * 0.15);
        if (x > gestureLockView.getLeft() + padding && x < gestureLockView.getRight() - padding &&
                y > gestureLockView.getTop() + padding && y < gestureLockView.getBottom() - padding
                ) {
            return true;
        }
        return false;
    }

    /**
     * 根据坐标点获取子view
     *
     * @param x
     * @param y
     * @return
     */
    private GestureLockView getChildIdByPos(int x, int y) {
        for (GestureLockView gestureLockView : mGestureLockViews) {
            if (checkPositionInChild(gestureLockView, x, y)) {
                return gestureLockView;
            }
        }
        return null;
    }

    private void changeItemMode() {
        for (GestureLockView gestureLockView : mGestureLockViews) {
            if (mChoose.contains(gestureLockView.getId())) {
                gestureLockView.setMode(GestureLockView.Mode.STATUS_FINGER_UP);
            }
        }
    }


    public void setListener(OnGestureLockViewListener listener) {
        this.mOnGestureLockViewListener = listener;
    }

    public void setAnswer(int[] answer) {
        this.mAnswer = answer;
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        if (mPath != null) {
            canvas.drawPath(mPath, mPaint);
        }
        if (mChoose.size() > 0) {
            if (mLastPathX != 0 && mLastPathY != 0) {
                canvas.drawLine(mLastPathX, mLastPathY, mTmpTarget.x, mTmpTarget.y, mPaint);
            }
        }
    }

    public interface OnGestureLockViewListener {
        /**
         * 单独选中元素的Id
         *
         * @param cId
         */
        public void onBlockSelected(int cId);

        /**
         * 是否匹配
         *
         * @param matched
         */
        public void onGestureEvent(boolean matched);

        /**
         * 超过尝试次数
         */
        public void onUnmatchedExceedBoundary();
    }
}

自定义的属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="color_no_finger_inner_circle" format="color"/>
    <attr name="color_no_finger_outer_circle" format="color"/>
    <attr name="color_finger_on" format="color"/>
    <attr name="color_finger_up" format="color"/>
    <attr name="count" format="integer"/>
    <attr name="tryTimes" format="integer"/>
    <declare-styleable name="GestureLockViewGroup">
        <attr name="color_no_finger_inner_circle"/>
        <attr name="color_no_finger_outer_circle" />
        <attr name="color_finger_on" />
        <attr name="color_finger_up" />
        <attr name="count" />
        <attr name="tryTimes" />
    </declare-styleable>
    
</resources>

布局调用,自定义的颜色没有加

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:attar="http://schemas.android.com/apk/armglobe.gesture"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="armglobe.gesture.MainActivity">

    <armglobe.gesture.GestureLockViewGroup
        android:id="@+id/getsturegroup"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#F2F2F7"
        android:gravity="center_vertical"
        attar:count="4"
        attar:tryTimes="5" />

</RelativeLayout>

Activity代码

public class MainActivity extends AppCompatActivity {
    GestureLockViewGroup gestureLockViewGroup;
    GestureLockViewGroup.OnGestureLockViewListener lockViewListener = new GestureLockViewGroup.OnGestureLockViewListener() {
        @Override
        public void onBlockSelected(int cId) {

        }

        @Override
        public void onGestureEvent(boolean matched) {
            if(matched){
                Toast.makeText(MainActivity.this,"正确",Toast.LENGTH_SHORT).show();
            }else {
                Toast.makeText(MainActivity.this,"错误",Toast.LENGTH_SHORT).show();
            }
        }

        @Override
        public void onUnmatchedExceedBoundary() {
            Toast.makeText(MainActivity.this,"已经超出最大重试次数",Toast.LENGTH_SHORT).show();
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        gestureLockViewGroup = (GestureLockViewGroup) findViewById(R.id.getsturegroup);
        gestureLockViewGroup.setListener(lockViewListener);
    }
}

好了手势解锁的代码就这些,下面可以开始看realm数据库的使用了,之前项目都是用的sql语句,反正写的要吐血,这次看看专门为移动的数据库会怎么样


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,448评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,019评论 4 62
  • 亲爱的朱: 今年的最后一天多了一秒,又可以多想你一秒。这一秒你说我在想什么呢?想你的容颜?想你的笑?想牵手的傻...
    弯路处的老橡树阅读 1,940评论 0 0
  • 2016年10月14日。被安排到 你不懂得安排时间 你不懂得利用时间 但请你珍惜我的时间 我很忙的 忙着睡觉 ...
    冰岛金鸣阅读 151评论 0 0