自定義View----帶進(jìn)度的返回頂部按鈕

效果

記得原來一直想實(shí)現(xiàn)以下這樣一個組件须板,最近抽時間完成了,花的時間也不多兢卵,實(shí)現(xiàn)起來也比較容易习瑰,算是自定義組件的另一種形式吧,最近入了自定義View的坑秽荤,寫了好幾個Demo
ToTopView
========

1.功能

1.滑動過程中:顯示進(jìn)度
2.滑動停止:顯示點(diǎn)擊返回頂部
3.點(diǎn)擊返回頂部

2.實(shí)現(xiàn)思路

1.滑動監(jiān)聽:滑動狀態(tài)+滑動位置
2.UI:重寫RelativeLayout甜奄,實(shí)現(xiàn)組件的覆蓋,底層:ImageView(頂部)窃款,頂層:LinearLayout(TextView(進(jìn)度)+View(線)+TextView(總量))利用Java代碼實(shí)現(xiàn)

3.關(guān)鍵代碼理解

1.初始化函數(shù)

private void Init(Context context, AttributeSet attrs) {
        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, 
                                R.styleable.ToTopView);
        mTextSize = typedArray.getDimensionPixelSize(R.styleable.
                             ToTopView_topTextSize,DEFAULT_CONTENT_TEXT_SIZE);
        mLineColor = typedArray.getColor(R.styleable.ToTopView_lineColor,
                getResources().getColor(R.color.colorAccent));
        mBacimg = typedArray.getResourceId(R.styleable.ToTopView_btnImg,
                       R.mipmap.btn_bring_to_top);
        typedArray.recycle();
        InitView(context);
    }

三個屬性可以自定義:
topTextSize:字體大小课兄。這里要注意一點(diǎn),這里返回的是px,我這里就使用的px晨继,如果想用sp烟阐,需要將px轉(zhuǎn)為sp

    public void setTextSize(float size) {  
    setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
    }

可以看到,源碼中如果只是setTextSize紊扬,默認(rèn)是以sp為單位的蜒茄。
我這里使用的是px

mTvProgress.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize);

lineColor:線的顏色,也就是進(jìn)度和總量中間的線的顏色
btnImg:ImageView的背景圖片

2.利用Java代碼繪制界面

private void InitView(Context context) {
        //圖片回到頂部
        mIvTop = new ImageView(context);
        mIvTop.setImageResource(mBacimg);
        LayoutParams params = new LayoutParams(
                DensityUtils.dp2px(context, 48), DensityUtils.dp2px(context, 48));
        params.addRule(RelativeLayout.CENTER_IN_PARENT);
        mIvTop.setLayoutParams(params);
        //滑動過程中顯示進(jìn)度
        mLlProgress = new LinearLayout(context);
        mLlProgress.setOrientation(LinearLayout.VERTICAL);
        mLlProgress.setBackgroundResource(R.drawable.bg_totop_progress);
        LayoutParams llparams = new LayoutParams(
                DensityUtils.dp2px(context, 48), LayoutParams.MATCH_PARENT);
        mLlProgress.setLayoutParams(llparams);
        mLlProgress.setGravity(Gravity.CENTER);
        //進(jìn)度
        mTvProgress = new TextView(context);
        mTvProgress.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize);
        mTvProgress.setGravity(Gravity.CENTER);
        LayoutParams tvparams = new LayoutParams(
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        mTvProgress.setLayoutParams(tvparams);
        //橫線
        View line = new View(context);
        line.setBackgroundColor(mLineColor);
        LayoutParams lineParams = new LayoutParams(ViewGroup.LayoutParams
                         .MATCH_PARENT, DensityUtils.dp2px(context, 1));
        line.setLayoutParams(lineParams);
        line.setPadding(DensityUtils.dp2px(context, 5), 0, 
                        DensityUtils.dp2px(context, 5), 0);
        //總量
        mTvMax = new TextView(context);
        mTvMax.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize);
        mTvMax.setGravity(Gravity.CENTER);
        mTvMax.setLayoutParams(tvparams);
        mLlProgress.addView(mTvProgress);
        mLlProgress.addView(line);
        mLlProgress.addView(mTvMax);

        addView(mIvTop);
        addView(mLlProgress);
    }

1.ImageView,都比較基礎(chǔ)餐屎,要注意兩個點(diǎn):
1).記得通過LayoutParams設(shè)置ImageView大小
2).設(shè)置ImageView在RelativeLayout中的Gravity(組件繼承的是RelativeLayout)
params.addRule(RelativeLayout.CENTER_IN_PARENT);(這個原來沒用過)

2.LinearLayout = TextView + View + TextView
這里主要都是通過Java代碼實(shí)現(xiàn)的檀葛,沒有通過xml實(shí)現(xiàn),算是原來沒有動手實(shí)現(xiàn)的腹缩,理解起來都比較簡單屿聋,唯一需要注意的就是要細(xì)心空扎,將該設(shè)置的屬性都要設(shè)置,尤其是LayoutParams,因?yàn)槭峭ㄟ^Java代碼實(shí)現(xiàn)润讥,不像xml那么直觀勺卢。

3.滑動監(jiān)聽

public void setRecyclerView(RecyclerView recyclerView) {
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                if (mScrollY >= getResources().getDisplayMetrics().heightPixels) {
                    setVisibility(View.VISIBLE);
                    if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                        //停止滑動
                        onShowState();
                    }
                    if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
                        //滑動
                        onScrolling();
                    }
                }
                super.onScrollStateChanged(recyclerView, newState);
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                mScrollY += dy;

                LinearLayoutManager manager = (LinearLayoutManager) recyclerView.getLayoutManager();
                int count = manager.getItemCount();
                int lastItemPosition = manager.findLastVisibleItemPosition();
                setProgress(lastItemPosition, count);

                super.onScrolled(recyclerView, dx, dy);
            }
        });

        initEvent(recyclerView);
    }

這里我用了依賴,將RecyclerView設(shè)置給了ToTopView象对,這里可能設(shè)計的不太全面,后面在研究設(shè)計模式的時候再來重構(gòu)一下宴抚。
1.監(jiān)聽滑動狀態(tài)變化

public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                if (mScrollY >= getResources().getDisplayMetrics().heightPixels) {
                    setVisibility(View.VISIBLE);
                    if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                        //停止滑動
                        onShowState();
                    }
                    if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
                        //滑動
                        onScrolling();
                    }
                }
                super.onScrollStateChanged(recyclerView, newState);
            }

如果滑動超過屏幕高度的時候后勒魔,顯示組件
停止滑動時->onShowState()

    /**
     * 滑動停止
     */
    public void onShowState() {
        mIvTop.setVisibility(VISIBLE);
        mLlProgress.setVisibility(GONE);
    }

顯示ImageView,隱藏LinearLayout
滑動過程中->onScrolling();

/**
     * 滑動過程中
     * 顯示進(jìn)度,隱藏Img
     */
    public void onScrolling() {
        mIvTop.setVisibility(GONE);
        mLlProgress.setVisibility(VISIBLE);
    }

2.監(jiān)聽滑動位置變化

public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                mScrollY += dy;

                LinearLayoutManager manager = (LinearLayoutManager) recyclerView
                                              .getLayoutManager();
                int count = manager.getItemCount();
                int lastItemPosition = manager.findLastVisibleItemPosition();
                setProgress(lastItemPosition, count);

                super.onScrolled(recyclerView, dx, dy);
            }

1)記錄滑動距離mScrollY
2)通過LinearLayoutManager的getItemCount方法獲得總量count
3)通過manager.findLastVisibleItemPosition()獲得當(dāng)前可見的最后一個個數(shù)菇曲,也就是當(dāng)前進(jìn)度

代碼基本上都挺簡單的冠绢,簡單的寫個博客記錄一下,附上GitHub地址常潮,具體代碼可見GitHub
https://github.com/sdfdzx/ToTopView

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末弟胀,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子喊式,更是在濱河造成了極大的恐慌孵户,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件岔留,死亡現(xiàn)場離奇詭異夏哭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)献联,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進(jìn)店門竖配,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人里逆,你說我怎么就攤上這事进胯。” “怎么了原押?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵胁镐,是天一觀的道長。 經(jīng)常有香客問我诸衔,道長希停,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任署隘,我火速辦了婚禮宠能,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘磁餐。我一直安慰自己违崇,他們只是感情好阿弃,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著羞延,像睡著了一般渣淳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上伴箩,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天入愧,我揣著相機(jī)與錄音,去河邊找鬼嗤谚。 笑死棺蛛,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的巩步。 我是一名探鬼主播旁赊,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼椅野!你這毒婦竟也來了终畅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤竟闪,失蹤者是張志新(化名)和其女友劉穎离福,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體炼蛤,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡术徊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鲸湃。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赠涮。...
    茶點(diǎn)故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖暗挑,靈堂內(nèi)的尸體忽然破棺而出笋除,到底是詐尸還是另有隱情,我是刑警寧澤炸裆,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布垃它,位于F島的核電站,受9級特大地震影響烹看,放射性物質(zhì)發(fā)生泄漏国拇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一惯殊、第九天 我趴在偏房一處隱蔽的房頂上張望酱吝。 院中可真熱鬧,春花似錦土思、人聲如沸务热。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽崎岂。三九已至捆毫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間冲甘,已是汗流浹背绩卤。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留江醇,地道東北人濒憋。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像嫁审,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子赖晶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評論 2 349

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,782評論 25 707
  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程律适,因...
    小菜c閱讀 6,367評論 0 17
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件遏插、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,065評論 4 62
  • 還沒放映之前捂贿,看網(wǎng)上的推薦,很期待胳嘲,期待什么厂僧,期待和他們一起去看看迷人的風(fēng)光,期待可以看看行走的自由了牛。 可是颜屠,看了...
    妖嬈的彼岸花閱讀 150評論 0 0
  • 我在車上,車在路上鹰祸,家在我的心上甫窟。 樹木在我的眼前,卻不在我的心上蛙婴。 人們在我的眼前粗井,卻不在我的心上。 你不在我的...
    沐小鳳閱讀 173評論 0 0