ListView在Android中非常的常见,然而系统给我们的ListView远远不能满足实际的需求。因此,就出现了很多的定制化的ListView,这里将简单的记录一下,ListView的常用拓展。
1.具有弹性的ListView
在Android中,ListView滑动到顶端或者低端的时候,并没有很多的提示。比如说,当ListView到了底端或者顶端,如果有一个弹性的效果,那就显得非常的友好。
这里将简单的记录一下怎么实现一个弹性的ListView。
在ListView的源代码中,有一个控制滑动边缘控制的方法
protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent)
有一个参数---maxOverScrollY,这个参数是用来控制ListView能够超出范围滑动的距离。在默认的情况下,它的值为0,我们可以通过来重写这个方法,然后改变这个值,从而可以控制一个ListView的滑动范围。
@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);
}
为了适配不同分辨率的手机,我们可以获得每个手机屏幕的密度--density来计算具体的值。
private void init(Context context) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
float density = metrics.density;
mMaxOverDistance = (int) (density * mMaxOverDistance);
}
2.自动显示、隐藏布局的ListView
当我们在ListView上滑动的时候,顶部ActionBar或者ToolBar就会相应的隐藏或者显示。
我们知道,让一个布局显示或者隐藏并带有动画效果,可以通过属性动画来实现。所以这个效果的关键就在于如何获得ListView的各种滑动事件。我们利用View的OnTouchListener接口来监听ListView的滑动,通过比较这次的坐标与上次的坐标的大小,来判断滑动的方向,并通过滑动的方向来判断是否需要隐藏或者显示相应的布局。
public class MainActivity extends AppCompatActivity implements OnTouchListener {
private ListView mListView = null;
private List mDatas = null;
private MyAdapter Adapter = null;
private int mFirstY = 0;
private int mMoveY = 0;
private int mTouchSlop = 0;
private boolean direction = false;
private boolean mShow = false;
private ObjectAnimator mAnimator = null;
private Toolbar mToolbar = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mListView = (ListView) findViewById(R.id.id_listView);
mDatas = new ArrayList();
for (int i = 0; i < 20; i++) {
mDatas.add("Title" + i);
}
Adapter = new MyAdapter(this, mDatas);
mListView.setAdapter(Adapter);
mListView.setOnTouchListener(this);
TextView header = new TextView(this);
mToolbar = (Toolbar) findViewById(R.id.id_toolBar);
header.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, mToolbar.getHeight()));
header.setText("1233");
mListView.addHeaderView(header);
mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
}
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mFirstY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE: {
mMoveY = (int) event.getY();
if(mMoveY - mFirstY > mTouchSlop)
{
//向上滑,状态栏应该显示
direction = false;
}
else if(mFirstY - mMoveY > mTouchSlop)
{
//向下滑,状态栏应该隐藏
direction = true;
}
//向下滑,则进行隐藏
if(direction)
{
//如果显示的话,则将其隐藏
if(mShow)
{
actionBarAnim(0); //隐藏
mShow = !mShow;
}
}
else //向上滑,则进行显示
{
if(!mShow)
{
actionBarAnim(1);
mShow = !mShow;
}
}
}
}
return false;
}
private void actionBarAnim(int flag)
{
if(mAnimator != null && mAnimator.isRunning())
{
mAnimator.cancel();
}
if(flag == 0) //隐藏
{
mAnimator = ObjectAnimator.ofFloat(mToolbar, "translationY",mToolbar.getTranslationY(), 0);
}
else if(flag == 1) //显示
{
mAnimator = ObjectAnimator.ofFloat(mToolbar, "translationY", mToolbar.getTranslationY(), -mToolbar.getHeight());
}
mAnimator.start();
}
}
3.聊天的ListView
通常我们使用的ListView每一个Item都有相同布局,所以展现出来的时候,除了数据不同的,其他的都是类似的。而我们熟知的QQ、微信等聊天APP,在聊天的界面上只有两种布局,即对方的消息布局和自己的消息布局这样的布局。
这样的布局其实可以在Adapter里面进行一些改变,在getView里面判断一下当前的item属于那种类型,不同的类型加载不同的layout布局文件。
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
Bean bean = mDatas.get(position);
if (convertView == null) {
holder = new ViewHolder();
if (bean.flag) {
convertView = mInflater.inflate(R.layout.item, parent, false);
holder.mTextView = (TextView) convertView.findViewById(R.id.id_textView);
} else {
convertView = mInflater.inflate(R.layout.item_layout, parent, false);
holder.mTextView = (TextView) convertView.findViewById(R.id.textView);
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.mTextView.setText(bean.content);
return convertView;
}
public class ViewHolder {
public TextView mTextView = null;
}