記得原來一直想實(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