Android實(shí)現(xiàn)網(wǎng)易Tab分類排序控件實(shí)現(xiàn)
先看看效果圖:

1、XML布局引入
<com.net168.lib.SortTabLayout android:id="@+id/layout" android:layout_width="match_parent" android:layout_height="wrap_content" />
2、設(shè)置數(shù)據(jù)源數(shù)據(jù),也就是每個(gè)item的對(duì)應(yīng)文本數(shù)據(jù)
//構(gòu)造數(shù)據(jù)源,暫時(shí)僅支持String
List<String> data = new ArrayList<String>();
for (int i = 0; i < 20; i ++) {
data.add("item" + i);
}
//設(shè)置數(shù)據(jù)源
vSortLayout.setShowData(data, 1);
3、設(shè)置,用于交互點(diǎn)擊和長(zhǎng)按的事件
vSortLayout.setOnSelectListener(new onSelectListener() {
//點(diǎn)擊事件,點(diǎn)擊Tab布局里面的item觸發(fā)
@Override
public void onSelect(View v, int index) {
Toast.makeText(MainActivity.this, "你點(diǎn)擊了item ,內(nèi)容為:" + ((TextView)v).getText(), Toast.LENGTH_SHORT).show();
}
//長(zhǎng)按事件,長(zhǎng)按Tab布局里面的item觸發(fā)
@Override
public void onLongSelect(View v) {
Toast.makeText(MainActivity.this, "長(zhǎng)按Tab,開(kāi)始排列", Toast.LENGTH_SHORT).show();
}
});
4、開(kāi)始排序和結(jié)束排序的接口
//如果參數(shù)是true的話,開(kāi)始排序,也就是可以拖動(dòng) vSortLayout.setIsMoveList(true); //結(jié)束排序,并且會(huì)返回選擇tab的當(dāng)前新位置 vSortLayout.getAndFinishSortData();
未完善的自定義功能
1、現(xiàn)在僅僅是支持String,并且布局也無(wú)法自定義,后續(xù)可能會(huì)完善Tab的item的View的自定義輸入
2、現(xiàn)在布局的行數(shù)和間距由硬代碼控制,并沒(méi)有形成簡(jiǎn)便易懂的接口
PS:調(diào)試間距的方法,主要調(diào)試下列幾個(gè)參數(shù)
/** * 配置參數(shù)區(qū)域 * mMaxRow : 每行的個(gè)數(shù) * Magin Width Tab的間隔和本身的寬度的占比 * 例如mMaxRow = 4,則寬度會(huì)由此策略分配 * |Magin|View|Magin|View|Magin|View|Magin|View|Magin| * 記控件寬度為這么分配 : 總寬度 = 5 * Magin + 4 * View, 而 Magin : View = mRowMagin : mRowWidth * 可以推導(dǎo)出各個(gè)控件的寬度,高度也如此計(jì)算 */ private final int mMaxRow = 4; private final int mRowMagin = 5; private final int mRowWidth = 26; private final int mColumnMagin = 4; private final int mColumnHeight = 10;
3、回滾不流暢,后期可以引入Scroller來(lái)控制緩慢回滾
實(shí)現(xiàn)原理
1、布局item排序采用基于ViewGroup的自定義布局,在onLayout的方法邏輯根據(jù)配置參數(shù)區(qū)域的參數(shù)進(jìn)行計(jì)算配置
@Override
protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
final int childCount = getChildCount();
int row = 0;
int column = 0;
int startWidth = 0;
int startHeight = 0;
for (int i = 0; i < childCount; i++) {
View childeView = childList.get(i);
row = i / 4;
column = i % 4;
startWidth = (int) ((column * (mRowWidth + 2 * mRowMagin) + mRowMagin) * mChildeItemSize);
startHeight = (int) ((row * (mColumnHeight + 2 * mColumnMagin) + mColumnMagin) * mChildeItemSize);
childeView.layout(startWidth ,startHeight ,(int)(startWidth + mRowWidth * mChildeItemSize),
(int)(startHeight + mColumnHeight * mChildeItemSize));
}
}
2、滑動(dòng)模塊部分,在onTouchEvent里面根據(jù)坐標(biāo)的捕獲,有坐標(biāo)分析出對(duì)應(yīng)的子Item,利用View.layout()方法讓拖動(dòng)的View跟隨手指移動(dòng),參加代碼
private void moveChildView(float x, float y) {
if (mMoveChildView != null) {
int left = (int) (((mChildIndex % 4) * (mRowWidth + 2 * mRowMagin) + mRowMagin) * mChildeItemSize);
int top = (int) (((mChildIndex / 4) * (mColumnHeight + 2 * mColumnMagin) + mColumnMagin) * mChildeItemSize);
int width = (int) (left + mRowWidth * mChildeItemSize);
int heigth = (int) (top + mColumnHeight * mChildeItemSize);
int moveX = (int) (x - beginX);
int moveY = (int) (y - beginY);
mMoveChildView.layout(left + moveX, top + moveY, width + moveX, heigth + moveY);
mMoveChildView.invalidate();
}
}
3、動(dòng)畫模塊,由于考慮低版本和不想引入過(guò)多的開(kāi)源庫(kù),故采用普通的動(dòng)畫實(shí)現(xiàn)
具體參見(jiàn)beginAnimation(final int start,final int end, boolean forward)方法。
4、整體流程
a、Touch的down事件,捕捉當(dāng)前的x、y數(shù)據(jù),計(jì)算出被移動(dòng)的View的所對(duì)應(yīng)index,并且其余view開(kāi)始抖動(dòng)動(dòng)畫
b、move事件,將被選中的view根據(jù)x、y利用layout方法進(jìn)行跟隨手指移動(dòng)
c、up事件,執(zhí)行位置調(diào)整動(dòng)畫,并且在調(diào)整完畢后,進(jìn)行新位置的設(shè)置
完整代碼:https://github.com/ganchuanpu/SortTabLayout.git
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android Activity 與Service進(jìn)行數(shù)據(jù)交互詳解
這篇文章主要介紹了Android Activity 與Service進(jìn)行數(shù)據(jù)交互的相關(guān)資料,在開(kāi)發(fā)Android App的時(shí)候經(jīng)常會(huì)使用這樣的功能,需要的朋友可以參考下2016-10-10
android選擇視頻文件上傳到后臺(tái)服務(wù)器
這篇文章主要介紹了android選擇視頻文件上傳到后臺(tái)服務(wù)器的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04
Android端使用Modbus協(xié)議的簡(jiǎn)單方法
Modbus協(xié)議是全球第一個(gè)用于工業(yè)現(xiàn)場(chǎng)的總線協(xié)議,與外設(shè)交互可以采用串口通信,tcp等方式,這篇文章主要給大家介紹了關(guān)于Android端使用Modbus協(xié)議的簡(jiǎn)單方法,需要的朋友可以參考下2021-11-11
Android 聽(tīng)筒模式的具體實(shí)現(xiàn)實(shí)例
這篇文章主要介紹了Android 聽(tīng)筒模式的具體實(shí)現(xiàn)實(shí)例,有需要的朋友可以參考一下2013-12-12
Android TextView實(shí)現(xiàn)詞組高亮的示例代碼
本篇文章主要介紹了Android TextView實(shí)現(xiàn)詞組高亮的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10
Android Handler實(shí)現(xiàn)閃屏頁(yè)倒計(jì)時(shí)代碼
這篇文章主要介紹了Android Handler實(shí)現(xiàn)閃屏頁(yè)倒計(jì)時(shí)代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08
Android實(shí)現(xiàn)文字滾動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)文字滾動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11
python gstreamer實(shí)現(xiàn)視頻快進(jìn)/快退/循環(huán)播放功能
這篇文章主要介紹了python gstreamer 實(shí)現(xiàn)視頻快進(jìn)/快退/循環(huán)播放功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03
Android打包上傳AAR文件到Maven倉(cāng)庫(kù)的示例
這篇文章主要介紹了Android打包上傳AAR文件到Maven倉(cāng)庫(kù)的示例,幫助大家更好的理解和學(xué)習(xí)使用Android開(kāi)發(fā),感興趣的朋友可以了解下2021-03-03

