ListView虽然应用广泛,但系统原生的ListView显然是不能满足用户在审美、功能上不断提高的需求。所以我们需要对原生的ListView进行拓展、修改。接下来实现一个具有弹性的ListView,Android默认的ListView在滚动到顶端或者底端的时候,并没有很好的提示。在Android5.X中,Google为这样的行为只添加了一个半月形的阴影效果。
而在IOS系统中,列表都是具有弹性的,即滚动的到底端或者顶端后会继续往下或者往上滑动一段距离。这样的设计会显得更加友好。我们也可以修改自己的ListView,让其也可以“弹性十足”。
网上有很多通过重写Listview来实现弹性效果的方法,比如增加HeaderView或者使用ScrollView进行嵌套,方法有很多,这里使用一种非常简单的方法来实现这个效果。这种方法虽然不如那些方法可定制高、效果丰富。但主要目的是让初学者学会如何从源码中找到问题的解决办法。
我们在查看ListView源代码的时候可以发现,ListView中有一个控制滑动到边缘的处理方法,如下所示:
protected boolean overScrollBy(int deltaX, int deltaY,
int scrollX, int scrollY,
int scrollRangeX, int scrollRangeY,
int maxOverScrollX, int maxOverScrollY,
boolean isTouchEvent)
可以看到这样一个参数:maxOverScrollY,注释中这样写到——Number of pixels to overscroll by in either direction along the Y axis。由此可以发现,虽然它的默认值是0,但其实只要修改这个参数的值,就可以让ListView具有弹性了!所以,重写这个方法,并将maxOverScrollY改为设置的值——mMaxOverDistance。代码如下所示:
@Override
protected boolean overScrollBy(int deltaX, int deltaY,
int scrollX, int scrollY,
int scrollRangeX, int scrollRangeY,
int maxOverScrollX, int maxOverScrollY,
boolean isTouchEvent) {
return super.overScrollBy(deltaX, deltaY,
scrollX, scrollY,
scrollRangeX, scrollRangeY,
maxOverScrollX, mMaxOverDistance, isTouchEvent);
}
这样,通过对这个值得修改,就实现了一个具有弹性的ListView了。效果如下所示:
当然,为了能够满足多分辨率的需求,我们可以在修改maxOverScrollY值得时候,可以通过屏幕的density来计算具体的值,让不同分辨率的弹性距离基本一致,代码如下所示:
private void initView() {
DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
float density = metrics.density;
mMaxOverDistance = (int) (density * mMaxOverDistance);
}
部分代码如下所示:
FlexibleListView.java
package com.example.mylistview;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.widget.ListView;
/**
* Created by CLF on 2016/8/24.
*/
public class FlexibleListView extends ListView {
private static int mMaxOverDistance = 50;
private Context mContext;
public FlexibleListView(Context context) {
super(context);
this.mContext = context;
initView();
}
public FlexibleListView(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
initView();
}
public FlexibleListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
initView();
}
private void initView() {
DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
float density = metrics.density;
mMaxOverDistance = (int) (density * mMaxOverDistance);
}
@Override
protected boolean overScrollBy(int deltaX, int deltaY,
int scrollX, int scrollY,
int scrollRangeX, int scrollRangeY,
int maxOverScrollX, int maxOverScrollY,
boolean isTouchEvent) {
return super.overScrollBy(deltaX, deltaY,
scrollX, scrollY,
scrollRangeX, scrollRangeY,
maxOverScrollX, mMaxOverDistance, isTouchEvent);
}
}
FlexibleListViewTest.java
package com.example.mylistview;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.widget.ArrayAdapter;
/**
* Created by CLF on 2016/8/24.
*/
public class FlexibleListViewTest extends AppCompatActivity {
private FlexibleListView mFlexibleListView;
private String[] data = new String[30];
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.flexible);
for (int i = 0; i < 30; i++) {
data[i] = ""+i;
}
mFlexibleListView = (FlexibleListView)findViewById(R.id.flexible_listview);
mFlexibleListView.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,data));
}
}