Android实现带进度返回顶部按钮

龙旋

共 6651字,需浏览 14分钟

 ·

2021-11-14 00:34

作者 |  被代码淹没的小伙子
地址 |  https://www.jianshu.com/p/72af8f950591

效果图


1、功能

1.滑动过程中:显示进度
2.滑动停止:显示点击返回顶部
3.点击返回顶部

2、实现思路

(1)、滑动监听:滑动状态+滑动位置
(2)、UI:重写RelativeLayout,实现组件的覆盖,底层:ImageView(顶部),顶层:LinearLayout(TextView(进度)+View(线)+TextView(总量))利用Java代码实现


3、关键代码理解


1、初始化函数

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转为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、ImageView,都比较基础,要注意两个点:

1)、记得通过LayoutParams设置ImageView大小
2)、设置ImageView在RelativeLayout中的Gravity(组件继承的是RelativeLayout),params.addRule(RelativeLayout.CENTER_IN_PARENT);(这个原来没用过)


2、LinearLayout = TextView + View + TextView
这里主要都是通过Java代码实现的,没有通过xml实现,算是原来没有动手实现的,理解起来都比较简单,唯一需要注意的就是要细心,将该设置的属性都要设置,尤其是LayoutParams,因为是通过Java代码实现,不像xml那么直观。


3、滑动监听

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设置给了ToTopView,这里可能设计的不太全面,后面在研究设计模式的时候再来重构一下。


1、监听滑动状态变化

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、监听滑动位置变化

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()获得当前可见的最后一个个数,也就是当前进度


源码地址:

https://github.com/DrownCoder/ToTopView


到这里就结束啦。
浏览 89
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报