Android 高级控件-ListView的扩展

  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;
    }
Android 高级控件-ListView的扩展_第1张图片

你可能感兴趣的:(Android 高级控件-ListView的扩展)