Use of ListView
Before we learn to use recyclerview, we must be struggling, hesitant, melancholy, confused in the world of ListView, but we can also go through this mess and enter a new world when we are really packaged.
Below you will find some pits in ListView that you have encountered in my project. Of course, you may also encounter pits in ListView, and there are different ways of handling them. This is only for those who know it, but for those who don't.
First, I'll send you a wave of'crashes'of all kinds of sliding conflicts I've encountered:
1) ScrollView internal application ListView, GridView scrolling conflict events
Processing method: Rewrite the onMeasure() method of ListView, code as follows
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;
public class MyListView extends ListView{
public MyListView(Context context) {
super(context);
}
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightSpec;
if (getLayoutParams().height==LayoutParams.WRAP_CONTENT){
heightSpec= MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE>>2,MeasureSpec.AT_MOST);
}else {
heightSpec=heightMeasureSpec;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
2) Solve scrolling issues with ScrolView nested ViewPager
Processing method: Rewrite the onMeasure() method of ScrolView, code as follows
Note: This may be the use of SimpleOnGestureListener, which is a class of different gesture handling when users touch the screen. The next article will give you detailed instructions on how to use it. Of course, if you are an old driver, you can also Baidu it directly, which also has a lot of reasonable explanations and instructions for use - -)
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.webkit.WebView;
import android.widget.ScrollView;
import android.widget.Scroller;
/**
* Customize ScrollView to fix: ScrollView nests ViewPager, causing ViewPager to not slide
*/
public class CustomScrollView extends ScrollView {
private GestureDetector mGestureDetector;
private int Scroll_height = 0;
private int view_height = 0;
protected Field scrollView_mScroller;
private static final String TAG = "CustomScrollView";
public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
mGestureDetector = new GestureDetector(context, new YScrollDetector());
setFadingEdgeLength(0);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
stopAnim();
}
boolean ret = super.onInterceptTouchEvent(ev);
boolean ret2 = mGestureDetector.onTouchEvent(ev);
return ret && ret2;
}
class YScrollDetector extends SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if (Math.abs(distanceY) > Math.abs(distanceX)) {
return true;
}
return false;
}
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
boolean stop = false;
if (Scroll_height - view_height == t) {
stop = true;
}
if (t == 0 || stop == true) {
try {
if (scrollView_mScroller == null) {
scrollView_mScroller = getDeclaredField(this, "mScroller");
}
Object ob = scrollView_mScroller.get(this);
if (ob == null || !(ob instanceof Scroller)) {
return;
}
Scroller sc = (Scroller) ob;
sc.abortAnimation();
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
super.onScrollChanged(l, t, oldl, oldt);
}
private void stopAnim() {
try {
if (scrollView_mScroller == null) {
scrollView_mScroller = getDeclaredField(this, "mScroller");
}
Object ob = scrollView_mScroller.get(this);
if (ob == null) {
return;
}
Method method = ob.getClass().getMethod("abortAnimation");
method.invoke(ob);
} catch (Exception ex) {
Log.e(TAG, e.getMessage());
}
}
@Override
protected int computeVerticalScrollRange() {
Scroll_height = super.computeVerticalScrollRange();
return Scroll_height;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (changed == true) {
view_height = b - t;
}
}
@Override
public void requestChildFocus(View child, View focused) {
if (focused != null && focused instanceof WebView) {
return;
}
super.requestChildFocus(child, focused);
}
/**
* Gets the hidden property of an object and sets the property to public to allow direct access
*
* @return {@link Field} Returns null if unreadable; returned Field s require the user to cache themselves; this method does not cache
*/
public static Field getDeclaredField(Object object, String field_name) {
Class<?> cla = object.getClass();
Field field = null;
for (; cla != Object.class; cla = cla.getSuperclass()) {
try {
field = cla.getDeclaredField(field_name);
field.setAccessible(true);
return field;
} catch (Exception e) {
}
}
return null;
}
}
3) Horizontal sliding conflict when ViewPager is applied internally
Processing method: Override onTouchEvent() method in ViewPager which slides horizontally inside, code as follows
import android.content.Context;
import android.graphics.PointF;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
/**
* Customize ViewPager to solve the problem of not sliding when ViewPagger is nested.
*/
public class HorizontalInnerViewPager extends ViewPager {
/** Points pressed when touching**/
PointF downP = new PointF();
/** Current point at touch**/
PointF curP = new PointF();
public HorizontalInnerViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
mGestureDetector = new GestureDetector(context, new XScrollDetector());
}
public HorizontalInnerViewPager(Context context) {
super(context);
mGestureDetector = new GestureDetector(context, new XScrollDetector());
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
curP.x = ev.getX();
curP.y = ev.getY();
if(ev.getAction() == MotionEvent.ACTION_DOWN){
downP.x = ev.getX();
downP.y = ev.getY();
getParent().requestDisallowInterceptTouchEvent(true);
}
if(ev.getAction() == MotionEvent.ACTION_MOVE){
getParent().requestDisallowInterceptTouchEvent(true);
}
return super.onTouchEvent(ev);
}
}
4) Nested ScrollView in ViewPager and another sliding conflict event in ScrollView
** Processing method:
1) Determine the nesting model: My nesting is ViewPager ->ScrollView ->ViewPager;
2) Horizontal scrolling of the innermost ViewPager always triggers the outermost ViewPager scrolling, which can be handled by customizing the internal ViewPager (using the same process in 3);
3) However, the outer ScrollView does not scroll when the innermost ViewPager scrolls vertically at this time (add the impleOnGestureListener gesture sliding listening method in 2).**
import android.content.Context;
import android.graphics.PointF;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
/**
* Customize ViewPager to solve the problem of not sliding when ViewPagger is nested.
*/
public class HorizontalInnerViewPager extends ViewPager {
/** Points pressed when touching**/
PointF downP = new PointF();
/** Current point at touch**/
PointF curP = new PointF();
/** Custom Gestures**/
private GestureDetector mGestureDetector;
public HorizontalInnerViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
mGestureDetector = new GestureDetector(context, new XScrollDetector());
}
public HorizontalInnerViewPager(Context context) {
super(context);
mGestureDetector = new GestureDetector(context, new XScrollDetector());
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
curP.x = ev.getX();
curP.y = ev.getY();
if(ev.getAction() == MotionEvent.ACTION_DOWN){
downP.x = ev.getX();
downP.y = ev.getY();
getParent().requestDisallowInterceptTouchEvent(true);
}
if(ev.getAction() == MotionEvent.ACTION_MOVE){
float distanceX = curP.x - downP.x;
float distanceY = curP.y - downP.y;
if(Math.abs(distanceX) > Math.abs(distanceY)){
getParent().requestDisallowInterceptTouchEvent(true);
}else{
getParent().requestDisallowInterceptTouchEvent(false);
}
}
return super.onTouchEvent(ev);
}
private class XScrollDetector extends GestureDetector.SimpleOnGestureListener{
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return (Math.abs(distanceX) > Math.abs(distanceY));
}
}
}
Not finished yet...