简书链接:androidtab单击到顶双击到顶部并刷新的解决方案
文章字数:685,阅读全文大约需要2分钟
首先要看tab是由什么打造的,我这里演示用我自己开发的增强版本RadioGroupX做Tabhost也就是 Fragment切换这个增加版高仿源码,所以各位我写的再垃圾也不会垃圾到哪里去。
也就是说高仿源码自然可以兼容老版本的 RadioGroup其实是增加了可以加badge 小红点功能。

实现思路
为了方便扩展,所以给触摸事件类传递一个接口PageControlX ,而不是一个activiy
给每一个tab设置触摸事件,设置之后原来的点击事件自然是不能触发了, 在自己实现的触摸类 编写具体业务逻辑,后寻找子fragment 或者view,所以我这里不写死为Fragment而是判断类型是否实现接口ITabActionX如果实现了ITabActionX就可以进行操作调用ITabActionX.doubleClickCheckITabActionX.simpleClickCheck,没有找到就判断是否实现了FragmentHolder 也就是有的可能是一层套一层的。 ITabActionX tabActonX = TopRefreshUtilX.findFinalFragmentByFragmentHolder(((FragmentHolder) fragment));就得到了最终的ITabActionX
到顶部方法呢基本上只需要调用 scrollView.scrollTo(0, 0); 或者 recyclerview.scrollToPosition(0);就可以实现到顶部.刷新呢,各位自己操作好了。难点就是考察大家是否会触摸事件的拦截操作了

给每一个tab设置触摸事件,设置之后原来的点击事件自然是不能触发了单击事件也需要借助触发·GestureDetectorCompat
另外避免重复切换需要判断index

1
2
3
4
5
6
 public boolean onSingleTapUp(MotionEvent e) {
if (pageControl.getCurrentItem() != index) {
pageControl.setCurrentItem(index);
return true;
}
}

双击的寻找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Override
public boolean onDoubleTap(MotionEvent e) {
int current = index;
//Prt.d(TAG, "onDoubleTap");
Object fragment = pageControl.getItem(current);
if (fragment instanceof ITabActionX) {
((ITabActionX) fragment).doubleClickCheck();
} else if (fragment instanceof FragmentHolder) {
ITabActionX tabActonX = TopRefreshUtilX.findFinalFragmentByFragmentHolder(((FragmentHolder) fragment));
if (tabActonX != null) {
tabActonX.doubleClickCheck();
}
}

return super.onDoubleTap(e);
}

我不太绘描述,还是直接上源码把。

MyTopTouchListener

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125


import android.support.v4.view.GestureDetectorCompat;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;


/**
* Created by qssq on 2018/3/21 [email protected]
*/
public class MyTopTouchListener implements View.OnTouchListener {
private final int index;
private PageControlX pageControl;


public MyTopTouchListener(PageControlX pageControl, int index) {
this.pageControl = pageControl;
this.index = index;
}
GestureDetectorCompat detector = new GestureDetectorCompat(AppContext.getInstance(), new GestureDetector.SimpleOnGestureListener() {
// GestureDetector detector = new GestureDetectorCompat(AppContext.getInstance(), new GestureDetector.SimpleOnGestureListener() {
//@返回TRUE如果事件被消耗,否则假
@Override
public boolean onSingleTapUp(MotionEvent e) {
if (pageControl.getCurrentItem() != index) {
pageControl.setCurrentItem(index);
return true;
} else {
Object fragment = pageControl.getItem(index);
if (fragment instanceof ITabActionX) {
((ITabActionX) fragment).simpleClickCheck();
} else if (fragment instanceof FragmentHolder) {
ITabActionX finalFragmentByFragmentHolder = TopRefreshUtilX.findFinalFragmentByFragmentHolder(((FragmentHolder) fragment));
if (finalFragmentByFragmentHolder != null) {
finalFragmentByFragmentHolder.simpleClickCheck();
}
}
return false;
}
}

@Override
public void onLongPress(MotionEvent e) {
//Prt.d(TAG, "onLongPress");
super.onLongPress(e);
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
//Prt.d(TAG, "onScroll");
return super.onScroll(e1, e2, distanceX, distanceY);
}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
//Prt.d(TAG, "onFling");
return super.onFling(e1, e2, velocityX, velocityY);
}

@Override
public void onShowPress(MotionEvent e) {
//Prt.d(TAG, "onShowPress");
super.onShowPress(e);
}

@Override
public boolean onDown(MotionEvent e) {
//Prt.d(TAG, "onDown");
return super.onDown(e);

}

@Override
public boolean onDoubleTap(MotionEvent e) {
int current = index;
//Prt.d(TAG, "onDoubleTap");
Object fragment = pageControl.getItem(current);
if (fragment instanceof ITabActionX) {
((ITabActionX) fragment).doubleClickCheck();
} else if (fragment instanceof FragmentHolder) {
ITabActionX tabActonX = TopRefreshUtilX.findFinalFragmentByFragmentHolder(((FragmentHolder) fragment));
if (tabActonX != null) {
tabActonX.doubleClickCheck();
}
}

return super.onDoubleTap(e);
}

@Override
public boolean onDoubleTapEvent(MotionEvent e) {
//Prt.d(TAG, "onDoubleTapEvent");
return super.onDoubleTapEvent(e);

}

/**
* 这个方法不同于onSingleTapUp,他是在GestureDetector确信用户在第一次触摸屏幕后,没有紧跟着第二次触摸屏幕,也就是不是“双击”的时候触发
* @param e
* @return
*/
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
//Prt.d(TAG, "onSingleTapConfirmed");
//有点慢。虽然确定是单击了
return true;
}

@Override
public boolean onContextClick(MotionEvent e) {
//Prt.d(TAG, "onContextClick");
return super.onContextClick(e);
}
});

@Override
public boolean onTouch(View v, MotionEvent event) {
detector.onTouchEvent(event);
return true;

// return super.onTouch(v,event);
}
}

未完待续。。。。

2018-3-21 17:46:58
继续 上代码

1
2
3
4
5
 binding.radioBtn1.setOnTouchListener(new MyTopTouchListener(this, 0));
binding.radioBtn2.setOnTouchListener(new MyTopTouchListener(this, 1));
binding.radioBtn3.setOnTouchListener(new MyTopTouchListener(this, 2));
binding.radioBtn4.setOnTouchListener(new MyTopTouchListener(this, 3));
binding.radiogroup.setOnCheckedChangeListener(this);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//递归寻找子fragment用
public interface FragmentHolder {
Object getCurrentFragment();
}
//通常回调给fragment 通知进行recycler的到顶部或者通知整个刷新
public interface ITabActionX {
void simpleClickCheck();
void doubleClickCheck();
}
//activity控制
public interface PageControlX {

int getCurrentItem();//用来判断是否已经选中,没选中就调用setCurrentItem

void setCurrentItem(int currentFixIndex);

Object getItem(int position);//拿到object 进行判断
}

MyFragment实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

@Override
public void simpleClickCheck() {

binding.nestedscrollview.scrollTo(0, 0);
}

@Override
public void doubleClickCheck() {
if (binding == null) {
return;
}
simpleClickCheck();
binding.swiperefreshLayout.setRefreshing(true);
queryInfo();

}

某嵌套fragment实现

1
2
3
4
5
6
7
@Override
public Object getCurrentFragment() {
return getFragments().get(binding.viewpager.getCurrentItem());

// return onGetFragment(binding.viewpager.getCurrentItem());

}

FragmentHolder 递归寻找工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class TopRefreshUtilX {
/**
* 找出真正可以刷新的fragment
*
* @param fragment
* @return
*/
public static ITabActionX findFinalFragmentByFragmentHolder(FragmentHolder fragment) {
Object currentFragment = fragment.getCurrentFragment();
if (currentFragment instanceof ITabActionX) {
return (ITabActionX) currentFragment;
} else if (currentFragment instanceof FragmentHolder) {
return findFinalFragmentByFragmentHolder((FragmentHolder) currentFragment);
} else {
return null;
}
}

}

scrollview嵌套recyclerview的到顶刷新

1
2
3
4
5
6
7
8
9
10
11
12
13
//    ITabActionX
@Override
public void simpleClickCheck() {

Prt.w(TAG, "hashCode:" + this.hashCode());
AppThemeUtils.scrollTop(getDataBind().recyclerview,getDataBind().scrollView);
}

@Override
public void doubleClickCheck() {
simpleClickCheck();
AppThemeUtils.refreshRefreshFragment(this);
}

滚动到顶部具体业务演示工具类,基本上可以解决大部分到顶部刷新,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void scrollTop(RecyclerView recyclerview, NestedScrollView scrollView) {
if (recyclerview != null) {
recyclerview.scrollToPosition(0);

}
if (scrollView != null) {
scrollView.scrollTo(0, 0);

}
}

public static void scrollTop(RecyclerView recyclerview) {
scrollTop(recyclerview,null);
}

MainActivity实现PageControlI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    @Override
public int getCurrentItem() {
View view = binding.radiogroup.findViewById(binding.radiogroup.getCheckedRadioButtonId());
int index = binding.radiogroup.indexOfChild(view);
if (index != -1) {

// View childAt = binding.radiogroup.getChildAt(index);
}
return index;
}

@Override
public void setCurrentItem(int currentFixIndex) {
View childAt = binding.radiogroup.getChildAt(currentFixIndex);
if (childAt instanceof Checkable) {
((Checkable) childAt).setChecked(true);
} else {
Prt.e(TAG, "index not is not support check");
}
}

@Override
public Fragment getItem(int position) {
return arrayList.get(position);
}