Android實現(xiàn)帶進度返回頂部按鈕
作者?|? 被代碼淹沒的小伙子 地址?|??https://www.jianshu.com/p/72af8f950591
效果圖

1、功能
2.滑動停止:顯示點擊返回頂部
3.點擊返回頂部
2、實現(xiàn)思路
(2)、UI:重寫RelativeLayout,實現(xiàn)組件的覆蓋,底層:ImageView(頂部),頂層:LinearLayout(TextView(進度)+View(線)+TextView(總量))利用Java代碼實現(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:字體大小。這里要注意一點,這里返回的是px,我這里就使用的px,如果想用sp,需要將px轉(zhuǎn)為sp
public void setTextSize(float size) {setTextSize(TypedValue.COMPLEX_UNIT_SP, size);}
可以看到,源碼中如果只是setTextSize,默認是以sp為單位的。
我這里使用的是px
mTvProgress.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize);lineColor:線的顏色,也就是進度和總量中間的線的顏色
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);//滑動過程中顯示進度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);//進度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)、記得通過LayoutParams設(shè)置ImageView大小
2)、設(shè)置ImageView在RelativeLayout中的Gravity(組件繼承的是RelativeLayout),params.addRule(RelativeLayout.CENTER_IN_PARENT);(這個原來沒用過)
這里主要都是通過Java代碼實現(xiàn)的,沒有通過xml實現(xiàn),算是原來沒有動手實現(xiàn)的,理解起來都比較簡單,唯一需要注意的就是要細心,將該設(shè)置的屬性都要設(shè)置,尤其是LayoutParams,因為是通過Java代碼實現(xiàn),不像xml那么直觀。
3、滑動監(jiān)聽
public void setRecyclerView(RecyclerView recyclerView) {recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {@Overridepublic 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);}@Overridepublic 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();
/*** 滑動過程中* 顯示進度,隱藏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);}
2)、通過LinearLayoutManager的getItemCount方法獲得總量count
3)、通過manager.findLastVisibleItemPosition()獲得當(dāng)前可見的最后一個個數(shù),也就是當(dāng)前進度
源碼地址:
https://github.com/DrownCoder/ToTopView
評論
圖片
表情
