Android 之 自定義控件 之 View

介紹:

Android的framework有大量的Views用來(lái)與用戶進(jìn)行交互并顯示不同種類的數(shù)據(jù),但是在實(shí)際開(kāi)發(fā)中經(jīng)常會(huì)遇到現(xiàn)有的UI控件不能滿足項(xiàng)目需求氮墨,或一個(gè)功能涉及到多個(gè)UI控件的組合,或?qū)崿F(xiàn)某一特效的UI,這時(shí)必須通過(guò)自定義View的方式,實(shí)現(xiàn)這些功能纤怒。

方式:

1.多個(gè)控件組合在一起
2.繼承至目前已經(jīng)提供的某個(gè)基礎(chǔ)的View
3.繼承至View或ViewGroup

View 和 ViewGroup的關(guān)系

View是基類芦昔,一般表示具體到某個(gè)控件栽惶,ViewGroup是它的子類迅脐,但又是layout的基類芍殖,一般作為一個(gè)視圖容器。由于ViewGroup是View的子類仪际,所以View的方法基本都有围小,但是View的直接子類不具備ViewGroup的屬性昵骤。雖然他們是繼承關(guān)系树碱,但是一般情況下我們可以看作是兩種形式,一種是控件变秦,一種是容器成榜。

View的三大核心方法onMeasure、onLayout蹦玫、onDraw

onMeasure:用于測(cè)量視圖的大惺昊椤;
onLayout:用于給視圖進(jìn)行布局樱溉;
onDraw:用于對(duì)視圖進(jìn)行繪制挣输;

View重繪方法

invalidate():
當(dāng)view的某些內(nèi)容發(fā)生變化的時(shí)候,需要調(diào)用invalidate來(lái)通知系統(tǒng)對(duì)這個(gè)view進(jìn)行重繪福贞。
requestLayout():
當(dāng)某些元素變化會(huì)引起組件大小變化時(shí)撩嚼,需要調(diào)用requestLayout方法。

開(kāi)始

1.繼承至View
為了讓Android Developer Tools能夠識(shí)別你的view挖帘,你必須至少提供一個(gè)構(gòu)造方法完丽,它包含一個(gè)Contenx與一個(gè)AttributeSet對(duì)象作為參數(shù)。這個(gè)狗雜哦方法允許布局編輯器創(chuàng)建并編輯你的view的實(shí)例拇舀。

public class MyView extends View {
    public MyView(Context context) {
        super(context);
    }
    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}

2.自定義屬性
為了添加一個(gè)內(nèi)置的View到你的UI上逻族,你需要通過(guò)XML屬性來(lái)指定它的樣式與行為。良好的自定義views可以通過(guò)XML添加來(lái)改變樣式骄崩,為了讓你的自定義的view也有如此的行為聘鳞,你應(yīng)該:

為你的view在資源標(biāo)簽下定義自設(shè)的屬性
在你的XML layout中指定屬性值
在運(yùn)行時(shí)獲取屬性值
把獲取到的屬性值應(yīng)用在你的view上

添加 資源文件到你的項(xiàng)目中薄辅。放置于res/values/attrs.xml文件中。

 <!--
    reference 參考某一資源ID
    dimension 尺寸值
    boolean:布爾值
    integer 整數(shù)型
    string  字符型
    color 顏色值
    ...等等

   名稱對(duì)應(yīng)你所建立的View類名
    -->
    <declare-styleable name="MyView">
        <attr name="titleName" format="string|reference"/>
        <attr name="icon" format="reference"/>
        <attr name="titleColor" format="color"/>
        <attr name="count" format="integer"/>
        <attr name="titleSize" format="dimension"/>
        <attr name="typeface">
              <enum name="normal" value="0" />
              <enum name="sans" value="1" />
              <enum name="serif" value="2" />
              <enum name="monospace" value="3" />
         </attr>
    </declare-styleable>
    

一旦你定義了自設(shè)的屬性抠璃,你可以在layout XML文件中使用它們长搀,就像內(nèi)置屬性一樣。唯一不同的是你自設(shè)的屬性是歸屬于不同的命名空間鸡典。不是屬于http://schemas.android.com/apk/res/android 的命名空間源请,它們歸屬于http://schemas.android.com/apk/res/你的包名
或者 使用http://schemas.android.com/apk/res-auto

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:custom="http://schemas.android.com/apk/res/com.example.customviews">
 <com.example.customviews.MyView
     custom:titleName="hello world"
     custom:titleColor="#333333"
     custom:typeface="normal" />
</LinearLayout>

當(dāng)view從XML layout被創(chuàng)建的時(shí)候,在xml標(biāo)簽下的屬性值都是從resource下讀取出來(lái)并傳遞到view的constructor作為一個(gè)AttributeSet參數(shù)彻况。盡管可以從AttributeSet中直接讀取數(shù)值谁尸,可是這樣做有些弊端:

擁有屬性的資源并沒(méi)有經(jīng)過(guò)解析
Styles并沒(méi)有運(yùn)用上

所以我們需要通過(guò)obtainStyledAttributes()來(lái)獲取屬性值。這個(gè)方法會(huì)傳遞一個(gè)TypedArray對(duì)象纽甘。

//TypedArray是一個(gè)用來(lái)存放由context.obtainStyledAttributes獲得的屬性的數(shù)組
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyView);
 try {
       CharSequence titlleName = a.getString(R.styleable.MyView_titleName, false);
       int count = a. getInteger(R.styleable.MyView_count, 0);
       int icon=a.getResourceId(R.styleable.MyView_icon, 0);
   } finally {
       a.recycle();
   }

TypedArray使用完成后一定要調(diào)用其recycle方法良蛮,否則會(huì)有內(nèi)存泄露的問(wèn)題

3.onDraw繪制
重繪一個(gè)自定義的view的最重要的步驟是重寫(xiě)onDraw()方法。onDraw()的參數(shù)是一個(gè)Canvas對(duì)象悍赢。Canvas類定義了繪制文本决瞳,線條,圖像與許多其他圖形的方法左权。你可以在onDraw方法里面使用那些方法來(lái)創(chuàng)建你的UI皮胡。在你調(diào)用任何繪制方法之前,你需要?jiǎng)?chuàng)建一個(gè)Paint對(duì)象赏迟。

android.graphics framework把繪制定義為下面兩類:
繪制什么屡贺,由Canvas處理
如何繪制,由Paint處理

常見(jiàn)的操作:
繪制文字使用drawText()锌杀。指定字體通過(guò)調(diào)用setTypeface(), 通過(guò)setColor()來(lái)設(shè)置文字顏色.
繪制基本圖形使用drawRect(), drawOval(), drawArc(). 通過(guò)setStyle()來(lái)指定形狀是否需要filled, outlined.
繪制一些復(fù)雜的圖形甩栈,使用Path類. 通過(guò)給Path對(duì)象添加直線與曲線, 然后使用drawPath()來(lái)繪制圖形. 和基本圖形一樣,paths也可以通過(guò)setStyle來(lái)設(shè)置是outlined, filled, both.
通過(guò)創(chuàng)建LinearGradient對(duì)象來(lái)定義漸變糕再。調(diào)用setShader()來(lái)使用LinearGradient量没。
通過(guò)使用drawBitmap來(lái)繪制圖片.
例:

/**
     * 
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        //drawRect(RectF rect, Paint paint) //繪制區(qū)域,參數(shù)一為RectF一個(gè)區(qū)域
        RectF rect = new RectF(10,100,300,300);
        mPaint.setStyle(Paint.Style.FILL);  //填充
        canvas.drawRect(rect,mPaint);


        //drawPath(Path path, Paint paint) //繪制一個(gè)路徑突想,參數(shù)一為Path路徑對(duì)象
        Path path = new Path();
        path.moveTo(50,500);   //設(shè)置起始點(diǎn)
        path.lineTo(100,720); //連接點(diǎn)
        path.lineTo(400,420); //連接點(diǎn)
        path.close();
        mPaint.setStyle(Paint.Style.FILL);    //畫(huà)筆
        mPaint.setColor(Color.BLUE);
        canvas.drawPath(path,mPaint);


        //貼圖
        //參數(shù)一就是我們常規(guī)的Bitmap對(duì)象殴蹄,
        //參數(shù)二是源區(qū)域(這里是bitmap)
        //參數(shù)三是目標(biāo)區(qū)域(應(yīng)該在canvas的位置和大小)
        //參數(shù)四是Paint畫(huà)刷對(duì)象
        //因?yàn)橛玫搅丝s放和拉伸的可能,當(dāng)原始Rect不等于目標(biāo)Rect時(shí)性能將會(huì)有大幅損失蒿柳。
        //drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)
        canvas.drawBitmap(mBitmap,500,500,mPaint);

        Rect src = new Rect(0,0,mBitmap.getWidth(),mBitmap.getHeight());  //想要繪制原圖的哪部分區(qū)域
        RectF dst = new RectF(200,200,500,800);  //繪制的位置
        canvas.drawBitmap(mBitmap,src,dst,mPaint);

         Matrix matrix = new Matrix();
        matrix.reset();

        //縮放
//        matrix.setScale(0.8f,0.8f);
        matrix.setRotate(30);
        canvas.drawBitmap(mBitmap,matrix,mPaint);


        //畫(huà)線饶套,
        //參數(shù)一起始點(diǎn)的x軸位置,
        //參數(shù)二起始點(diǎn)的y軸位置垒探,
        //參數(shù)三終點(diǎn)的x軸水平位置妓蛮,
        //參數(shù)四y軸垂直位置,
        //最后一個(gè)參數(shù)為Paint 畫(huà)刷對(duì)象圾叼。
        //drawLine(float startX, float startY, float stopX, float stopY, Paintpaint)
        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mPaint.setStrokeWidth(20);  //設(shè)置線寬
        canvas.drawLine(50f,50f,200f,200f,mPaint);

        //畫(huà)點(diǎn)蛤克,參數(shù)一水平x軸捺癞,參數(shù)二垂直y軸,第三個(gè)參數(shù)為Paint對(duì)象构挤。
        //drawPoint(float x, float y, Paint paint)
        canvas.drawPoint(500f,500f,mPaint);

        //渲染文本髓介,Canvas類除了上面的還可以描繪文字,
        //參數(shù)一是String類型的文本筋现,
        //參數(shù)二x軸唐础,
        //參數(shù)三y軸,
        //參數(shù)四是Paint對(duì)象矾飞。
        //drawText(String text, float x, floaty, Paint paint)
        mPaint.setStrokeWidth(1);
        canvas.drawText("CD1605",800F,400F,mPaint);

        //方法一膨,該方法可以沿著Path繪制文本
        // 其中hOffset參數(shù)指定水平偏移 (文本間距)
        // vOffset參數(shù)指定垂直偏移(距離線頂部的間距)
        canvas.drawTextOnPath("天行健,君子以自強(qiáng)不息",path,-20,80,mPaint);

        //畫(huà)橢圓洒沦,
        //參數(shù)一是掃描區(qū)域 即 橢圓區(qū)域
        //參數(shù)二為paint對(duì)象豹绪;
        //drawOval(RectF oval, Paint paint)
        RectF oval = new RectF(300f,800f,600f,900f);
        canvas.drawOval(oval,mPaint);
        //API>=21
//        canvas.drawOval(200f,500f,600f,800f,mPaint);


        // 繪制圓,
        // 參數(shù)一是中心點(diǎn)的x軸申眼,
        // 參數(shù)二是中心點(diǎn)的y軸瞒津,
        // 參數(shù)三是半徑,
        // 參數(shù)四是paint對(duì)象括尸;
        //drawCircle(float cx, float cy, float radius,Paint paint)
        mPaint.setARGB(255,100,255,255);
        canvas.drawCircle(700,700,100,mPaint);

        //畫(huà)弧
        //參數(shù)一是RectF對(duì)象巷蚪,一個(gè)矩形區(qū)域橢圓形的界限用于定義在形狀、大小姻氨、弧钓辆,
        //參數(shù)二是起始角(度)在電弧的開(kāi)始,
        //參數(shù)三掃描角(度)開(kāi)始順時(shí)針測(cè)量的肴焊,
        //參數(shù)四是如果這是真的話,包括橢圓中心的電弧,并關(guān)閉它,如果它是假這將是一個(gè)弧線,
        //參數(shù)五是Paint對(duì)象;
        //drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
        RectF arc = new RectF(300f,1200f,600f,1400f);
        mPaint.setARGB(255,100,100,255);
        mPaint.setStyle(Paint.Style.STROKE);
        canvas.drawArc(arc,0,180,false,mPaint);




        // 線性渲染
        // 其中功戚,參數(shù)x0表示漸變的起始點(diǎn)x坐標(biāo)娶眷;
        // 參數(shù)y0表示漸變的起始點(diǎn)y坐標(biāo);
        // 參數(shù)x1表示漸變的終點(diǎn)x坐標(biāo)啸臀;
        // 參數(shù)y1表示漸變的終點(diǎn)y坐標(biāo)〗斐琛;
        // color0表示漸變開(kāi)始顏色乘粒;
        // color1表示漸變結(jié)束顏色豌注;
        // 參數(shù)tile表示平鋪方式。
        Shader mShader = new LinearGradient(
                0, 0, 100, 100,
                new int[] { Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW,
                        Color.LTGRAY }, null, Shader.TileMode.REPEAT); // 一個(gè)材質(zhì),打造出一個(gè)線性梯度沿著一條線灯萍。

        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mPaint.setShader(mShader);
        RectF oval2 = new RectF(60, 100, 200, 240);// 設(shè)置個(gè)新的長(zhǎng)方形轧铁,掃描測(cè)量
        canvas.drawArc(oval2, 200, 130, true, mPaint);
        // 畫(huà)弧,第一個(gè)參數(shù)是RectF:該類是第二個(gè)參數(shù)是角度的開(kāi)始旦棉,第三個(gè)參數(shù)是多少度齿风,第四個(gè)參數(shù)是真的時(shí)候畫(huà)扇形药薯,是假的時(shí)候畫(huà)弧線


        //畫(huà)貝塞爾曲線
        mPaint.reset();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.GREEN);
        mPaint.setStrokeWidth(20);
        Path path2=new Path();
        path2.moveTo(100, 320);//設(shè)置Path的起點(diǎn)

        // x1,y1為控制點(diǎn)的坐標(biāo)值救斑,x2童本,y2為終點(diǎn)的坐標(biāo)值;
        // 貝塞爾曲線的形成脸候,就比如我們把一條橡皮筋拉直穷娱,橡皮筋的頭尾部對(duì)應(yīng)起點(diǎn)和終點(diǎn),
        // 然后從拉直的橡皮筋中選擇任意一點(diǎn)(除頭尾對(duì)應(yīng)的點(diǎn)外)扯動(dòng)橡皮筋形成的彎曲形狀运沦,
        // 而那個(gè)扯動(dòng)橡皮筋的點(diǎn)就是控制點(diǎn)

        path2.quadTo(300, 310, 170, 400); //設(shè)置貝塞爾曲線的控制點(diǎn)坐標(biāo)和終點(diǎn)坐標(biāo)
//        path2.close();//閉合繪制
        canvas.drawPath(path2, mPaint);//畫(huà)出貝塞爾曲線

        //繪制 畫(huà)布 
        //canvas.drawColor(Color.YELLOW);
        //清空 或者 
        //canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
    }

**4.onMeasure **
為了正確的繪制你的view鄙煤,你需要知道view的大小。復(fù)雜的自定義view通常需要根據(jù)在屏幕上的大小與形狀執(zhí)行多次layout計(jì)算茶袒。而不是假設(shè)這個(gè)view在屏幕上的顯示大小梯刚。即使只有一個(gè)程序會(huì)使用你的view,仍然是需要處理屏幕大小不同薪寓,密度不同亡资,方向不同所帶來(lái)的影響。
盡管view有許多方法是用來(lái)計(jì)算大小的向叉,但是大多數(shù)是不需要重寫(xiě)的锥腻。如果你的view不需要特別的控制它的大小,唯一需要重寫(xiě)的方法是[onSizeChanged()](http://developer.android.com/reference/android/view/View.html#onSizeChanged(int, int, int, int)).
onSizeChanged()母谎,當(dāng)你的view第一次被賦予一個(gè)大小時(shí)瘦黑,或者你的view大小被更改時(shí)會(huì)被執(zhí)行。在onSizeChanged方法里面計(jì)算位置奇唤,間距等其他與你的view大小值幸斥。
當(dāng)你的view被設(shè)置大小時(shí),layout manager(布局管理器)假定這個(gè)大小包括所有的view的內(nèi)邊距(padding)咬扇。當(dāng)你計(jì)算你的view大小時(shí)甲葬,你必須處理內(nèi)邊距的值。這段MyView.onSizeChanged()
代碼演示:

     // Account for padding
       float xpad = (float)(getPaddingLeft() + getPaddingRight());
       float ypad = (float)(getPaddingTop() + getPaddingBottom());

       // Account for the label
       if (mShowText) xpad += mTextWidth;

       float ww = (float)w - xpad;
       float hh = (float)h - ypad;

       // Figure out how big we can make the pie.
       float diameter = Math.min(ww, hh);

如果你想更加精確的控制你的view的大小懈贺,需要重寫(xiě)[onMeasure()](http://developer.android.com/reference/android/view/View.html#onMeasure(int, int))方法经窖。這個(gè)方法的參數(shù)是View.MeasureSpec,它會(huì)告訴你的view的父控件的大小梭灿。那些值被包裝成int類型画侣,你可以使用靜態(tài)方法來(lái)獲取其中的信息。

/**
     * 布局測(cè)量
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        //MeasureSpec通常翻譯為”測(cè)量規(guī)格”,它是一個(gè)32位的int數(shù)據(jù).
        //其中高2位代表SpecMode即某種測(cè)量模式堡妒,低30位為SpecSize代表在該模式下的規(guī)格大小.
        //getMode 獲取設(shè)置的模式AT_MOST配乱、EXACTLY、UNSPECIFIED
    
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        int width=0,height=0;

        if(widthMode ==MeasureSpec.AT_MOST){
            //寬度類型為warp_content ,
            //此處如果布局設(shè)置為 warp_content我們將width設(shè)置為200PX(這個(gè)高度應(yīng)該是你自己繪制的區(qū)域高度)
            width = 200宪卿;
        }else if(widthMode ==MeasureSpec.EXACTLY){
            //寬度類型為match_parent 或者定義好的dp值得的诵,此處我們?cè)O(shè)置為控件測(cè)量獲取的父容器所給予的寬度
            width = widthSize;
        }else if(widthMode ==MeasureSpec.UNSPECIFIED){
            //表示子布局想要多大就多大,一般出現(xiàn)在AadapterView的item的heightMode中佑钾、ScrollView的childView的heightMode中西疤;此種模式比較少見(jiàn),一般用不到
        }

        if(heightMode ==MeasureSpec.AT_MOST){
            //高度類型為warp_content
            //此處如果布局設(shè)置為 warp_content我們將height設(shè)置為200PX(這個(gè)高度應(yīng)該是你自己繪制的區(qū)域高度)
            height = 200;
        }else if(heightMode ==MeasureSpec.EXACTLY){
            //高度類型為match_parent 或者定義好的dp值得休溶,此處我們?cè)O(shè)置為控件測(cè)量獲取的父容器所給予的高度
            height = heightSize;
        }else if(heightMode ==MeasureSpec.UNSPECIFIED){
            //表示子布局想要多大就多大代赁,一般出現(xiàn)在AadapterView的item的heightMode中、ScrollView的childView的heightMode中兽掰;此種模式比較少見(jiàn)芭碍,一般用不到
        }

        //設(shè)置控件寬高
        setMeasuredDimension(width,height);
    }

上面的代碼有2個(gè)重要的事情需要注意:

1.計(jì)算的過(guò)程有把view的最好把padding考慮進(jìn)去。這部分是view所控制的孽尽。(此處的示例代碼 沒(méi)有給出)
2.onMeasure()沒(méi)有返回值窖壕。它通過(guò)調(diào)用setMeasuredDimension()來(lái)獲取結(jié)果。調(diào)用這個(gè)方法是強(qiáng)制執(zhí)行的杉女,如果你遺漏了這個(gè)方法瞻讽,會(huì)出現(xiàn)運(yùn)行時(shí)異常。

4.onTouchEvent給你的view添加觸摸動(dòng)作
有些時(shí)候我們需要給我們的View添加一些手指按下熏挎,移動(dòng)速勇,抬起的操作,這時(shí)候就需要重寫(xiě) View 的 onTouchEvent方法坎拐。

/**
     * 事件觸發(fā)
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                Log.e(TAG,"按下:("+event.getX()+":"+event.getY()+")");
                break;
            case MotionEvent.ACTION_MOVE:
                Log.e(TAG,"移動(dòng):("+event.getX()+":"+event.getY()+")");
                break;
            case MotionEvent.ACTION_UP:
                Log.e(TAG,"抬起:("+event.getX()+":"+event.getY()+")");
                break;
        }
        //消費(fèi)事件
        return true;
    }

很多時(shí)候onTouch本身并不能滿足我們的需求烦磁,比如快速滑動(dòng)View時(shí)的速度等,這時(shí)候就需要借助另外一個(gè)Android給我們提供的另一個(gè)touch事件GestureDetector

class mListener extends GestureDetector.SimpleOnGestureListener {
   @Override
   public boolean onDown(MotionEvent e) {
       return true;
   }
}
mDetector = new GestureDetector(PieChart.this.getContext(), new ```
不管你是否使用GestureDetector.SimpleOnGestureListener, 你必須總是實(shí)現(xiàn)onDown()方法哼勇,并返回true都伪。這一步是必須的,因?yàn)樗械膅estures都是從onDown()開(kāi)始的猴蹂。如果你在onDown()里面返回false院溺,系統(tǒng)會(huì)認(rèn)為你想要忽略后續(xù)的gesture,那么GestureDetector.OnGestureListener的其他回調(diào)方法就不會(huì)被執(zhí)行到了。一旦你實(shí)現(xiàn)了GestureDetector.OnGestureListener并且創(chuàng)建了GestureDetector的實(shí)例, 你可以使用你的GestureDetector來(lái)中止你在onTouchEvent里面收到的touch事件磅轻。

Override
public boolean onTouchEvent(MotionEvent event) {
boolean result = mDetector.onTouchEvent(event);
if (!result) {
if (event.getAction() == MotionEvent.ACTION_UP) {
stopScrolling();
result = true;
}
}
return result;
}

當(dāng)你傳遞一個(gè)touch事件到onTouchEvent()時(shí),若這個(gè)事件沒(méi)有被辨認(rèn)出是何種gesture逐虚,它會(huì)返回false聋溜。你可以執(zhí)行自定義的gesture-decection代碼。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末叭爱,一起剝皮案震驚了整個(gè)濱河市撮躁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌买雾,老刑警劉巖把曼,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杨帽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡嗤军,警方通過(guò)查閱死者的電腦和手機(jī)注盈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)叙赚,“玉大人老客,你說(shuō)我怎么就攤上這事≌鸲#” “怎么了胧砰?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)苇瓣。 經(jīng)常有香客問(wèn)我尉间,道長(zhǎng),這世上最難降的妖魔是什么击罪? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任哲嘲,我火速辦了婚禮,結(jié)果婚禮上外邓,老公的妹妹穿的比我還像新娘撤蚊。我一直安慰自己,他們只是感情好损话,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布侦啸。 她就那樣靜靜地躺著,像睡著了一般丧枪。 火紅的嫁衣襯著肌膚如雪光涂。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天拧烦,我揣著相機(jī)與錄音忘闻,去河邊找鬼。 笑死恋博,一個(gè)胖子當(dāng)著我的面吹牛齐佳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播债沮,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼炼吴,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了疫衩?” 一聲冷哼從身側(cè)響起硅蹦,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后童芹,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體涮瞻,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年假褪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了署咽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嗜价,死狀恐怖艇抠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情久锥,我是刑警寧澤家淤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站瑟由,受9級(jí)特大地震影響絮重,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜歹苦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一青伤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧殴瘦,春花似錦狠角、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至屉凯,卻和暖如春立帖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背悠砚。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工晓勇, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人灌旧。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓绑咱,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親枢泰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子羡玛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,162評(píng)論 25 707
  • 本文整理自: Google 官方文檔之自定義 View,筆者省略了對(duì)自己幫助不大的章節(jié)宗苍,拜讀原文請(qǐng)點(diǎn)鏈接。 一、繼...
    程序員K哥閱讀 416評(píng)論 0 3
  • 6讳窟、View的繪制 (1)當(dāng)測(cè)量好一個(gè)View之后让歼,我們就可以簡(jiǎn)單的重寫(xiě) onDraw()方法,并在 Canvas...
    b5e7a6386c84閱讀 1,895評(píng)論 0 3
  • 親愛(ài)的F, 又是新的一天补箍,昨晚睡前告訴自己改执,一定不要辜負(fù)今天。 所以希望今天的你坑雅,做好自己該做的工作辈挂,另外,一定要...
    凣凣閱讀 123評(píng)論 0 0
  • 沒(méi)去過(guò)的地方裹粤,都叫遠(yuǎn)方~~
    missyou欲言閱讀 211評(píng)論 0 0