自定义View----带进度的返回顶部按钮
2017-04-10 17:12
531 查看
记得原来一直想实现以下这样一个组件,最近抽时间完成了,花的时间也不多,实现起来也比较容易,算是自定义组件的另一种形式吧,最近入了自定义View的坑,写了好几个Demo
ToTopView
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:字体大小。这里要注意一点,这里返回的
4000
是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()获得当前可见的最后一个个数,也就是当前进度
代码基本上都挺简单的,简单的写个博客记录一下,附上GitHub地址,具体代码可见GitHub
https://github.com/sdfdzx/ToTopView
相关文章推荐
- 自定义view--带进度显示的下载按钮
- Android自定义View之圆形进度条式按钮
- Material Design系列,自定义Behavior之上滑显示返回顶部按钮
- Material Design系列,自定义Behavior之上滑显示返回顶部按钮
- Android 自定义View——带进度条按钮
- 自定义导航返回按钮是用customView不可以的原因?
- 不通过push,给viewcontroller自定义UINavigationBar,并加上返回按钮
- Android自定义View——圆形进度条式按钮
- Android自定义view,titlebar的返回按钮
- 自定义View 绘制进度按钮(ProgressButton)
- android中webview显示网页、进度条显示进度、上一页、下一页、支持放大缩小、返回按钮2秒两次点击退出应用
- IOS让返回按钮显示自定义标题而不是上个ViewController的title
- Material Design系列,自定义Behavior之上滑显示返回顶部按钮
- UITableView 状态栏返回顶部 和自定义按钮返回顶部
- 自定义首选项_添加顶部布局(返回按钮)
- navigationController push的view不添加返回按钮
- android 自定义按钮实现 home键 和返回键
- 使用findViewById查找自定义view时返回NULL问题
- android带返回按钮的自定义标题栏
- 自定义默认生成的导航栏 标题 颜色 返回按钮