第四章 ListView使用技巧

ListView的使用范围非常广泛,尽管RecycleView在很多地方取代了ListView,但是ListView的地位还是难以撼动的。
那么这一章节的知识点,将通过代码的方式展示出来:

ListView的重要属性

    <com.why.a4_listview.MyListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        /**
         * 这两个属性控制分割线和分割线的高度,
         * android:divider="null"是把分割线设置为了透明,也就是去掉了分割线
         **/
        android:divider="@android:color/darker_gray"
        /**
         * 取消进度条
         **/
        android:scrollbars="none"
        /**
         * 设置点击listview的item的点击效果,下面是使得点击效果为透明状态,也就是取消了点击效果
         **/
        android:listSelector="@android:color/transparent"
        >

    </com.why.a4_listview.MyListView>

ListView的使用

public class MainActivity extends Activity {

    private List<ChatItemListViewBean> mChatData;;

    private MyListView listView;
    private List<String> mData;
    private Toolbar mToolbar;
    private int mTouchSlop;
    private boolean mShow = true;
    private float mFirstY;
    private int direction;
    private Animator mAnimator;
    private View.OnTouchListener myTouchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()){
                case MotionEvent.ACTION_DOWN:
                    Log.i("test", "ACTION_DOWN: ");
                    mFirstY = event.getY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    Log.i("test", "ACTION_MOVE: ");
                    float currentY = event.getY();
                    if (currentY - mFirstY > 0){
                        //向下滑动
                        direction = 0;
                    }else if (mFirstY - currentY > 0){
                        //向上滑动
                        direction = 1;
                    }

                    if (direction == 1){
                        if (mShow){
                            toolbarAnim(0);//隐藏
                            mShow = !mShow;
                        }
                    }else if (direction == 0){
                        if (!mShow){
                            toolbarAnim(1);//显示
                            mShow = !mShow;
                        }
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    Log.i("test", "ACTION_UP: ");
                    break;
            }
            return false;
        }
    };

    private void toolbarAnim(int flag) {
        if (mAnimator != null && mAnimator.isRunning()){
            mAnimator.cancel();
        }
        if (flag == 0){ //隐藏
            //效果一样
            //mAnimator = ObjectAnimator.ofFloat(mToolbar, "translationY", 0, -mToolbar.getHeight());
            mAnimator = ObjectAnimator.ofFloat(mToolbar, "translationY", mToolbar.getTranslationY(), -mToolbar.getHeight());
        }else {  //显示
            //mAnimator = ObjectAnimator.ofFloat(mToolbar, "translationY", -mToolbar.getHeight(), 0);
            mAnimator = ObjectAnimator.ofFloat(mToolbar, "translationY", mToolbar.getTranslationY(), 0);
        }
        mAnimator.start();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initChat();
    }

    private void initChat() {
        initToolBar();
        mToolbar.setVisibility(View.GONE);
        initChatData();
        listView = (MyListView) findViewById(R.id.lv);
        listView.setAdapter(new ChatListViewAdapter(getApplicationContext(), mChatData));
    }

    private void initText() {
        initToolBar();
        initData();
        textListView();
        initText();
    }


    private void initToolBar() {
        mToolbar = findViewById(R.id.toolbar);
    }

    private void initData() {
        mData = new ArrayList<>();
        for (int i=0; i<20; i++){
            mData.add(String.valueOf(i));
        }

        /**
         * 获得系统认为的最低的滑动距离
         */
        mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
    }

    private void textListView() {
        listView = (MyListView) findViewById(R.id.lv);
        listView.setAdapter(new ViewHolderAdapter(getApplicationContext(), mData));
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                /**
                 * 瞬间移动到 position 为11的item上,position 为11的item出现在第一行
                 */
                //listView.setSelection(11);
                /**
                 * 平滑移动到position为20的item上,
                 *   但是当从上向下滑动的时候,20出现在屏幕的最后一行
                 *   从下向上滑动的时候,20出现在屏幕的第一行
                 */
                //listView.smoothScrollToPosition(20);
                /**
                 * -25是指向上移动25个item, 25是指向下移动25个item
                 */
                //listView.smoothScrollByOffset(25);
                /**
                 * 在2秒内向下移动500个px
                 */
                //listView.smoothScrollBy(500, 2000);
                /**
                 * 获取第20个子view
                 */
                //View childView = listView.getChildAt(20);
            }
        });

        /**
         * 当listview为空数据的时候,要显示的布局
         */
        if (mData.size() == 0){
            listView.setEmptyView(findViewById(R.id.iv_empty));
        }

        listView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                /**
                 * 可以根据用户滑动的方向,并在不同的事件中进行相应的;逻辑处理
                 */
                switch (event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        break;
                    case MotionEvent.ACTION_MOVE:
                        break;
                    case MotionEvent.ACTION_UP:
                        break;
                }
                return false;
            }
        });

        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                switch (scrollState){
                    /**
                     * 滑动停止
                     */
                    case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
                        Log.i("test", "滑动停止---SCROLL_STATE_IDLE: ");
                        break;
                    /**
                     * 正在滑动
                     */
                    case SCROLL_STATE_TOUCH_SCROLL:
                        Log.i("test", "正在滑动---SCROLL_STATE_TOUCH_SCROLL: ");
                        break;
                    /**
                     * 手指用力滑动屏幕导致形成惯性的时候,此时手指离开屏幕后,listview由于惯性继续滑动的时候走这里
                     *  如果手指力道不能形成惯性,那么当前方法只会调用两次
                     *  如果足以形成惯性,会调用三次,而不是一直调用走这里
                     */
                    case SCROLL_STATE_FLING:
                        Log.i("test", "惯性滑动---SCROLL_STATE_FLING: ");
                        break;
                }
            }

            /**
             * 滚动时一直调用该方法
             *   firstVisibleItem 当前能看到的第一个item的id(从0开始)
             *   visibleItemCount 当前能看到的item的总数(没有显示完全的item也包含在内)
             *   totalItemCount 整个listview的item总数
             */
            int lastVisibleItem;
            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                Log.i("test", "onScroll: ");
                /**
                 * 判断是否到了最后一行
                 */
                if (firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount > 0){
                    Log.i("test", "到底了: ");
                }

                if (firstVisibleItem > lastVisibleItem){
                    Log.i("test", "向上滑动: ");
                }else if (firstVisibleItem < lastVisibleItem){
                    Log.i("test", "向下滑动: ");
                }
                lastVisibleItem = firstVisibleItem;
            }
        });

        /**
         * 获取可视区域内第一个item的position
         * 不滑动获取到的值为0
         */
        int firstVisiblePosition = listView.getFirstVisiblePosition();
        Log.i("test", "firstVisiblePosition: "+firstVisiblePosition);

        /**
         * 获取可视区域内最后一个item的position
         * 没有滑动的时候,得到的值为-1,原因getChildCount()获取到的值为0
         */
        int lastVisiblePosition = listView.getLastVisiblePosition();
        Log.i("test", "最后一个item: "+lastVisiblePosition);

        addHeaderView();

        listView.setOnTouchListener(myTouchListener);
    }

    /**
     * 为防止第一个元素被toolbar遮挡,应该添加头部
     */
    private void addHeaderView() {
        View header = new View(this);
        header.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT,
                (int) getResources().getDimension(R.dimen.abc_action_bar_default_height_material)));
        listView.addHeaderView(header);
    }
}

ListView弹性效果的设置

当上滑到头或者下滑到底的时候,需要有个弹性效果,下面自定义的 ListView 能够达到一个简易的弹性效果。

public class MyListView extends ListView {
    private int mMaxOverDistance = 300;

    public MyListView(Context context) {
        this(context, null);
    }

    public MyListView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initData(context);
    }

    /**
     * 满足多分辨率的要求,根据屏幕density来计算具体的值
     * @param context
     */
    private void initData(Context context) {
        DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
        float density = displayMetrics.density;
        mMaxOverDistance = (int) (density*mMaxOverDistance);
    }

    /**
     * 重写该方法,在listview中maxOverScrollY的值默认为0;
     *   我将修改为mMaxOverDistance。使得listview滑动到边界的时候,能够有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);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值