自定義seekbar詳解

自定義view之seekbar

本文簡介:在github上找了不少seekbar贩耐,有些庫具備相當(dāng)復(fù)雜的功能狭魂,所以我想自己寫一個(gè)簡單易用的seekbar。本文主要講述為什么要自定義view肋层,自定義view的大體步驟橄妆,編寫重難點(diǎn)。

1倒彰、為什么要自定義view

由于工作上的需要审洞,我們往往需要實(shí)現(xiàn)某種特殊的布局或者界面效果,這時(shí)候官方?jīng)]有提供相應(yīng)的控件支持待讳,需要我們繼承view或者其它view類擴(kuò)展芒澜。一般初學(xué)者入門可以先嘗試組合view,即先自己利用多個(gè)官方控件拼裝成需要的效果创淡,然后內(nèi)置邏輯(參考本人的數(shù)量加減view)痴晦。也就是把a(bǔ)bc等多個(gè)view組合在一起使用,比include方式多了內(nèi)置邏輯的好處琳彩。(具體范例參考本人其它博客)

接下來本文講述的是如何自定義一個(gè)seekbar誊酌。先看效果圖,如下露乏。

這里寫圖片描述

2碧浊、分析要繪制的自定義view

1)根據(jù)最終效果圖或者需求方提供的功能說明等,去分析界面效果包含哪些動(dòng)作瘟仿,比如手勢(shì)(點(diǎn)擊箱锐,觸摸移動(dòng)),要顯示的圖形形狀劳较、文本(矩形驹止,原型,弧形观蜗,隨圖形一起繪制的文本等等臊恋,都要仔細(xì)分析),拆解view圖形為小的模塊墓捻。

2)比如本文的seekbar抖仅,明顯分為3個(gè)部分,一個(gè)是后面刻度的進(jìn)度條砖第,一個(gè)是當(dāng)前的進(jìn)度條撤卢。還有一個(gè)圓形按鈕。然后手指點(diǎn)擊刻度條厂画,會(huì)根據(jù)點(diǎn)擊位置當(dāng)前進(jìn)度跳轉(zhuǎn)至此,并且圓形按鈕也是如此拷邢。有一個(gè)特殊的需求是可以圓角也可以無圓角袱院,并且圓形按鈕可有可無。所以需要2個(gè)標(biāo)記boolean去區(qū)分。需要注意的一點(diǎn)是忽洛,按照習(xí)慣一般圓形按鈕的圓心的x所在坐標(biāo)應(yīng)該是在白色的當(dāng)前進(jìn)度的最右邊x坐標(biāo)腻惠。

3)根據(jù)圖片,我們可以得出欲虚,3個(gè)模塊的繪制都是自己有自身的大小控制集灌,而為了適配左右padding,所以的繪制進(jìn)度條時(shí)复哆,要預(yù)留padding欣喧。
而上下padding,我不準(zhǔn)備處理梯找,直接讓seekbar繪制在縱向的中間即可唆阿。即縱坐標(biāo)y中心點(diǎn)都是height/2,并且限制3個(gè)模塊的最大高度為view的高度锈锤,避免繪制出界驯鳖。

3、自定義view主要方法介紹

主要方法有onmeasure久免、ondraw浅辙、ontouchevent、構(gòu)造函數(shù)阎姥。自定義view一般圍繞這幾個(gè)方法進(jìn)行處理记舆,構(gòu)造函數(shù)里獲取自定義屬性的值,初始化paint等對(duì)象丁寄,初始化一些view參數(shù)氨淌。ondraw進(jìn)行繪制圖形,這個(gè)主要有drawarc等方法伊磺,這個(gè)不多講盛正,自行搜索相關(guān)方法總覽。ontouchevent就是處理點(diǎn)擊坐標(biāo)屑埋,然后觸發(fā)一些繪制操作或響應(yīng)某個(gè)方法動(dòng)作豪筝。對(duì)于viewgroup的話還有onlayout等方法。

4摘能、開始繪制

先準(zhǔn)備本view需要的自定義屬性续崖,3個(gè)模塊的高度大小、是否圓角团搞、顏色等严望。tickBar是刻度條,circlebutton是圓形按鈕逻恐,progress就是當(dāng)前進(jìn)度住涉,代碼如下。

 <!--自定義 seekbar-->
    <declare-styleable name="NumTipSeekBar">
        <attr name="tickBarHeight" format="dimension"/>
        <attr name="tickBarColor" format="color"/>
        <attr name="circleButtonColor" format="color"/>
        <attr name="circleButtonTextColor" format="color"/>
        <attr name="circleButtonTextSize" format="dimension"/>
        <attr name="circleButtonRadius" format="dimension"/>
        <attr name="progressHeight" format="dimension"/>
        <attr name="progressColor" format="color"/>
        <attr name="selectProgress" format="integer"/>
        <attr name="startProgress" format="integer"/>
        <attr name="maxProgress" format="integer"/>
        <attr name="isShowButtonText" format="boolean"/>
        <attr name="isShowButton" format="boolean"/>
        <attr name="isRound" format="boolean"/>
    </declare-styleable>

接下來就是獲取自定義屬性促煮,然后初始化view參數(shù)了。TypedArray對(duì)象一定要記得attr.recycle();關(guān)閉姆涩,一般textsize是getDimension,而高度大小什么的是獲取getDimensionPixelOffset惭每,view本身測(cè)試出來的也是px值骨饿,但是settextsize的方法需要傳入dp或者sp值。我在initview方法里初始化所需要的paint對(duì)象台腥,避免ondraw反復(fù)繪制里new對(duì)象耗費(fèi)不必要的內(nèi)存宏赘。可能初學(xué)者不清楚RectF是什么東西览爵,你百度一下會(huì)死啊置鼻。。蜓竹。代碼如下箕母。

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

    public NumTipSeekBar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
 public NumTipSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }


    /**
     * 初始化view的屬性
     *
     * @param context
     * @param attrs
     */
    private void init(Context context, AttributeSet attrs) {

        TypedArray attr = context.obtainStyledAttributes(attrs, R.styleable.NumTipSeekBar);
        mTickBarHeight = attr.getDimensionPixelOffset(R.styleable
                .NumTipSeekBar_tickBarHeight, getDpValue(8));
        mTickBarColor = attr.getColor(R.styleable.NumTipSeekBar_tickBarColor, getResources()
                .getColor(R.color.orange_f6));
        mCircleButtonColor = attr.getColor(R.styleable.NumTipSeekBar_circleButtonColor,
                getResources().getColor(R.color.white));
        mCircleButtonTextColor = attr.getColor(R.styleable.NumTipSeekBar_circleButtonTextColor,
                getResources().getColor(R.color.purple_82));
        mCircleButtonTextSize = attr.getDimension(R.styleable
                .NumTipSeekBar_circleButtonTextSize, getDpValue(16));
        mCircleButtonRadius = attr.getDimensionPixelOffset(R.styleable
                .NumTipSeekBar_circleButtonRadius, getDpValue(16));
        mProgressHeight = attr.getDimensionPixelOffset(R.styleable
                .NumTipSeekBar_progressHeight, getDpValue(20));
        mProgressColor = attr.getColor(R.styleable.NumTipSeekBar_progressColor,
                getResources().getColor(R.color.white));
        mSelectProgress = attr.getInt(R.styleable.NumTipSeekBar_selectProgress, 0);
        mStartProgress = attr.getInt(R.styleable.NumTipSeekBar_startProgress, 0);
        mMaxProgress = attr.getInt(R.styleable.NumTipSeekBar_maxProgress, 10);
        mIsShowButtonText = attr.getBoolean(R.styleable.NumTipSeekBar_isShowButtonText, true);
        mIsShowButton = attr.getBoolean(R.styleable.NumTipSeekBar_isShowButton, true);
        mIsRound = attr.getBoolean(R.styleable.NumTipSeekBar_isRound, true);
        initView();

        attr.recycle();


    }
     private void initView() {
        mProgressPaint = new Paint();
        mProgressPaint.setColor(mProgressColor);
        mProgressPaint.setStyle(Paint.Style.FILL);
        mProgressPaint.setAntiAlias(true);

        mCircleButtonPaint = new Paint();
        mCircleButtonPaint.setColor(mCircleButtonColor);
        mCircleButtonPaint.setStyle(Paint.Style.FILL);
        mCircleButtonPaint.setAntiAlias(true);

        mCircleButtonTextPaint = new Paint();
        mCircleButtonTextPaint.setTextAlign(Paint.Align.CENTER);
        mCircleButtonTextPaint.setColor(mCircleButtonTextColor);
        mCircleButtonTextPaint.setStyle(Paint.Style.FILL);
        mCircleButtonTextPaint.setTextSize(mCircleButtonTextSize);
        mCircleButtonTextPaint.setAntiAlias(true);

        mTickBarPaint = new Paint();
        mTickBarPaint.setColor(mTickBarColor);
        mTickBarPaint.setStyle(Paint.Style.FILL);
        mTickBarPaint.setAntiAlias(true);

        mTickBarRecf = new RectF();//矩形,一會(huì)根據(jù)這個(gè)繪制刻度條在這個(gè)矩形內(nèi)
        mProgressRecf = new RectF();
        mCircleRecf = new RectF();
    }

由于本view沒有太大必要編寫onmeasure方法去適配wrapcontent俱济。所以接下來就是ondraw里進(jìn)行繪制了嘶是。首先我們先繪制刻度條,首先獲取當(dāng)前view的高寬蛛碌,刻度條設(shè)置的高寬聂喇,然后計(jì)算y坐標(biāo)中心,計(jì)算出剛才RectF矩形范圍蔚携。要設(shè)置上下左右的坐標(biāo)起點(diǎn)希太,左就是getPaddingLeft()作為起點(diǎn),即默認(rèn)自定義view支持paddingleft的設(shè)置酝蜒。top的起點(diǎn)就是(mViewHeight - mTickBarHeight) / 2誊辉,即含義是繪制在view縱坐標(biāo)y的中心點(diǎn),然后tickbar高度從此點(diǎn)分為上下2半亡脑。同理求出橫向的終點(diǎn)的x坐標(biāo)以及底部坐標(biāo)等

  @Overrid
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();
        initValues(width, height);
        // do........
    }

  private void initValues(int width, int height) {
        mViewWidth = width - getPaddingRight() - getPaddingLeft();
        mViewHeight = height;
        if (mTickBarHeight > mViewHeight) {
            //如果刻度條的高度大于view本身的高度的1/2堕澄,則顯示不完整,所以處理下霉咨。
            mTickBarHeight = mViewHeight;
        }
        mTickBarRecf.set(getPaddingLeft(), (mViewHeight - mTickBarHeight) / 2,
                mViewWidth + getPaddingLeft(), mTickBarHeight / 2 +
                        mViewHeight / 2);


      

同理處理進(jìn)度條部分的繪制蛙紫,這個(gè)比剛才多了一層邏輯,起點(diǎn)依舊途戒,但是終點(diǎn)x(矩形的right坐標(biāo))需要根據(jù)當(dāng)前進(jìn)度計(jì)算坑傅。mSelectProgress 是當(dāng)前進(jìn)度值,mMaxProgress 是最大值喷斋,mStartProgress是默認(rèn)起點(diǎn)代表多少刻度值唁毒,比如1-10的seekbar效果(起點(diǎn)是1矢渊,終點(diǎn)是10)。求出比值然后乘以view本身的實(shí)際繪制范圍的寬度(上面代碼有計(jì)算)枉证,加上paddingleft,得出矩形的終點(diǎn)x移必。

  mCirclePotionX = (float) (mSelectProgress - mStartProgress) /
                (mMaxProgress - mStartProgress) * mViewWidth + getPaddingLeft();
  if (mProgressHeight > mViewHeight) {
            //如果刻度條的高度大于view本身的高度的1/2室谚,則顯示不完整,所以處理下崔泵。
            mProgressHeight = mViewHeight;
        }

        mProgressRecf.set(getPaddingLeft(), (mViewHeight - mProgressHeight) / 2,
                mCirclePotionX, mProgressHeight / 2 + mViewHeight / 2);

同理求出圓形按鈕的坐標(biāo)范圍

    if (mCircleButtonRadius > mViewHeight / 2) {
            //如果圓形按鈕的半徑大于view本身的高度的1/2秒赤,則顯示不完整,所以處理下憎瘸。
            mCircleButtonRadius = mViewHeight / 2;
        }
        mCircleRecf.set(mCirclePotionX - mCircleButtonRadius, mViewHeight / 2 -
                        mCircleButtonRadius / 2,
                mCirclePotionX + mCircleButtonRadius, mViewHeight / 2 +
                        mCircleButtonRadius / 2);

開始繪制入篮,mIsRound控制圓角。重點(diǎn)說明的是 Paint.FontMetricsInt處理文本的居中顯示幌甘。
代碼如下潮售。

  @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();
        initValues(width, height);
       
        if (mIsRound) {
            canvas.drawRoundRect(mTickBarRecf, mProgressHeight / 2, mProgressHeight / 2,
                    mTickBarPaint);
            canvas.drawRoundRect(mProgressRecf, mProgressHeight / 2, mProgressHeight / 2,
                    mProgressPaint);
        } else {
            canvas.drawRect(mTickBarRecf, mTickBarPaint);
            canvas.drawRect(mProgressRecf, mProgressPaint);
        }
//        canvas.drawArc(mCircleRecf, 0, 360, true, mCircleButtonPaint);
        if (mIsShowButton) {
            canvas.drawCircle(mCirclePotionX, mViewHeight / 2, mCircleButtonRadius,
                    mCircleButtonPaint);
        }
        if (mIsShowButtonText) {
            Paint.FontMetricsInt fontMetrics = mCircleButtonTextPaint.getFontMetricsInt();
            int baseline = (int) ((mCircleRecf.bottom + mCircleRecf.top - fontMetrics.bottom -
                    fontMetrics
                            .top) / 2);
            // 下面這行是實(shí)現(xiàn)水平居中,drawText對(duì)應(yīng)改為傳入targetRect.centerX()
            canvas.drawText(String.valueOf(mSelectProgress), mCircleRecf.centerX
                            (), baseline,
                    mCircleButtonTextPaint);

        }
    }

5锅风、處理觸摸邏輯

這里主要是依賴onTouchEvent判斷手勢(shì)酥诽,當(dāng)event滿足某個(gè)觸摸條件就進(jìn)行獲取當(dāng)前坐標(biāo)計(jì)算進(jìn)度。本view是ACTION_MOVE皱埠、ACTION_DOWN時(shí)觸發(fā)肮帐。isEnabled判斷是否設(shè)置setEnabled屬性,如果設(shè)置則屏蔽觸摸繪制边器,這是我的特殊需求训枢。judgePosition()主要是根據(jù)x坐標(biāo)進(jìn)行計(jì)算進(jìn)度。BigDecimal 是處理四舍五入忘巧,大概發(fā)生進(jìn)度變化時(shí)重新繪制自身view恒界。return true;是為了消費(fèi)觸摸事件。(觸摸事件分發(fā)機(jī)制袋坑,請(qǐng)移步大牛的博客)

   @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!isEnabled()) {
            //如果設(shè)置不可用仗处,則禁用觸摸設(shè)置進(jìn)度
            return false;
        }
        float x = event.getX();
        float y = event.getY();
//        Log.i(TAG, "onTouchEvent: x:" + x);
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                judgePosition(x);
                return true;
            case MotionEvent.ACTION_DOWN:
                judgePosition(x);
                return true;
            case MotionEvent.ACTION_UP:
                if (mOnProgressChangeListener != null) {
                    Log.i(TAG, "onTouchEvent: 觸摸結(jié)束,通知監(jiān)聽器-mSelectProgress:"+mSelectProgress);
                    mOnProgressChangeListener.onChange(mSelectProgress);
                }
                return true;
            default:
                break;
        }

        return super.onTouchEvent(event);
    }

    private void judgePosition(float x) {
        float end = getPaddingLeft() + mViewWidth;
        float start = getPaddingLeft();
        int progress = mSelectProgress;
//        Log.i(TAG, "judgePosition: x-start:" + (x - start));
//        Log.i(TAG, "judgePosition: start:" + start + "  end:" + end + "  mMaxProgress:" +
//                mMaxProgress);
        if (x >= start) {
            double result = (x - start) / mViewWidth * (float) mMaxProgress;
            BigDecimal bigDecimal = new BigDecimal(result).setScale(0, BigDecimal.ROUND_HALF_UP);
//            Log.i(TAG, "judgePosition: progress:" + bigDecimal.intValue() + "  result:" + result
//                    + "  (x - start) / end :" + (x - start) / end);
            progress = bigDecimal.intValue();
            if (progress > mMaxProgress) {
//                Log.i(TAG, "judgePosition:x > end  超出坐標(biāo)范圍:");
                progress = mMaxProgress;
            }
        } else if (x < start) {
//            Log.i(TAG, "judgePosition: x < start 超出坐標(biāo)范圍:");
            progress = 0;
        }
         if (progress != mSelectProgress) {
            //發(fā)生變化才通知view重新繪制
            setSelectProgress(progress, false);
        }

    }

下面是一些主要的set方法枣宫,用來更新view婆誓。

      /**
     * 設(shè)置當(dāng)前選中的值
     *
     * @param selectProgress 進(jìn)度
     */
    public void setSelectProgress(int selectProgress) {
        this.setSelectProgress(selectProgress, true);
    }

    /**
     * 設(shè)置當(dāng)前選中的值
     *
     * @param selectProgress   進(jìn)度
     * @param isNotifyListener 是否通知progresschangelistener
     */
    public void setSelectProgress(int selectProgress, boolean isNotifyListener) {
        getSelectProgressValue(selectProgress);
        Log.i(TAG, "mSelectProgress: " + mSelectProgress + "  mMaxProgress: " +
                mMaxProgress);
        if (mOnProgressChangeListener != null && isNotifyListener) {
            mOnProgressChangeListener.onChange(mSelectProgress);
        }
        invalidate();
    }


    /**
     * 計(jì)算當(dāng)前選中的進(jìn)度條的值
     *
     * @param selectProgress 進(jìn)度
     */
    private void getSelectProgressValue(int selectProgress) {
        mSelectProgress = selectProgress;
        if (mSelectProgress > mMaxProgress) {
            mSelectProgress = mMaxProgress;
        } else if (mSelectProgress <= mStartProgress) {
            mSelectProgress = mStartProgress;
        }
    }


自此本seekbar基本講述完畢,觀看下面源碼也颤,可以了解詳細(xì)的內(nèi)容洋幻,每個(gè)字段都有注釋,初學(xué)者可以進(jìn)行源碼查看翅娶。
源碼地址:https://github.com/389273716/highscalabilityseekbar

下一篇預(yù)告:
刻度盤view文留,支持外部倒計(jì)時(shí)控制好唯,支持觸摸移動(dòng),點(diǎn)擊燥翅,帶動(dòng)畫骑篙,支持配置界面元素,適配屏幕森书。


這里寫圖片描述
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末靶端,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子凛膏,更是在濱河造成了極大的恐慌杨名,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件猖毫,死亡現(xiàn)場離奇詭異台谍,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)吁断,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門趁蕊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人仔役,你說我怎么就攤上這事介衔。” “怎么了骂因?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵炎咖,是天一觀的道長。 經(jīng)常有香客問我寒波,道長乘盼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任俄烁,我火速辦了婚禮绸栅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘页屠。我一直安慰自己粹胯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布辰企。 她就那樣靜靜地躺著风纠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪牢贸。 梳的紋絲不亂的頭發(fā)上竹观,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼臭增。 笑死懂酱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的誊抛。 我是一名探鬼主播列牺,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼拗窃!你這毒婦竟也來了昔园?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤并炮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后甥郑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逃魄,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年澜搅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了伍俘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡勉躺,死狀恐怖癌瘾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情饵溅,我是刑警寧澤妨退,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站蜕企,受9級(jí)特大地震影響咬荷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜轻掩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一幸乒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧唇牧,春花似錦罕扎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扮惦,卻和暖如春宴咧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背径缅。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國打工掺栅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留烙肺,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓氧卧,卻偏偏與公主長得像桃笙,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子沙绝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,501評(píng)論 25 707
  • 動(dòng)物園里某阿姨 匆匆忙忙去喂食 多虧呼救得及時(shí) 遲了成為虎口食 注:飼養(yǎng)員剛要喂食搏明,門沒關(guān)嚴(yán),老虎逃出來闪檬,多虧自救...
    旖旎i閱讀 326評(píng)論 2 11
  • flask-cache redis
    老男人一枚的博客閱讀 955評(píng)論 0 0
  • 學(xué)校泳池建造粗悯,更多注重安全性 現(xiàn)在很多學(xué)校開始建造泳池了虚循,然而很多學(xué)校卻不知道如何建造泳池,泳池要如何設(shè)計(jì)比較合理...
    六點(diǎn)泳池閱讀 416評(píng)論 0 0
  • 誰不曾有過行尸走肉的日子 我剛好處在這段日子里样傍,并且不知何時(shí)才能走出這段難熬的日子横缔。 工作上遇到瓶頸,有心無力的那...
    YOU日記閱讀 594評(píng)論 0 0