您的位置:首页 > 其它

自定义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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: