【学习笔记】ListView初识

  1. 处理空ListView

    之前在做空数据的时候,会在ListView同界面再放一个其它控件,然后在ListView数据为空时,将控件显示,有数据再隐藏。

     最近发现有方法直接处理: ListView处理空数据时,可用通过方法setEmptyView()来设置空数据布局


    看效果:
        

    代码如下:

    布局文件:
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <Button
            android:id="@+id/btn_data"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="有数据"/>
        <Button
            android:id="@+id/btn_nodata"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="无数据"/>
        <ListView
            android:id="@+id/mListView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"></ListView>
        <!--ListView 数据为空时 显示下面默认的图片-->
        <ImageView
            android:id="@+id/empty_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/pic1"/>
    </LinearLayout>



    程序代码:
    private ListView mListView;
        private Button btn_data;
        private Button btn_nodata;
        private Context context;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_list_view);
            context = this;
            initView();
        }
    
        private void initView(){
            btn_data = (Button)findViewById(R.id.btn_data);
            btn_nodata = (Button)findViewById(R.id.btn_nodata);
            btn_data.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    String[] datas = {"item1", "item2"};
                    mListView.setAdapter(new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, datas));
                }
            });
            btn_nodata.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    String[] datas = {};
                    mListView.setAdapter(new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, datas));
                }
            });
            mListView = (ListView)findViewById(R.id.mListView);
            mListView.setEmptyView(findViewById(R.id.empty_view));
    
        }




  2. ListView滑动监听

    工作时间也不短了,一直忙着做项目,除了自己会的那点基础,有很多是多拼凑一段代码,西拼凑一段代码。

    常用就是到github上找开源库,直接使用。

    但是时间一长,遇到一些特殊需求,就很难搞定。所以,搞定原理还是很重要的。


    2.1 OnTouchListener事件

    OnTouchListener是View中的监听事件,
    通过监听ACTION_DOWN、ACTION_MOVE、ACTION_UP这三个事件发生时的坐标,就可以根据坐标判断用户滑动的方向,
    并在不同的事件中进行相应的逻辑处理,使用代码如下所示:

    mListView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View view, MotionEvent motionEvent) {
                    switch (motionEvent.getAction()){
                        case MotionEvent.ACTION_DOWN:
                            //触摸时操作
                            break;
                        case MotionEvent.ACTION_MOVE:
                            //移动时操作
                            break;
                        case MotionEvent.ACTION_UP:
                            //离开时操作
                            break;
                    }
                    return false;
                }
            });





    2.2 OnScrollListener事件
    mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(AbsListView absListView, int scrollState) {
                    switch (scrollState){
                        case SCROLL_STATE_IDLE:
                            //滑动停止时
                            Log.d("Test", "SCROLL_STATE_IDLE");
                            break;
                        case SCROLL_STATE_TOUCH_SCROLL:
                            //正在滚动
                            Log.d("Test", "SCROLL_STATE_TOUCH_SCROLL");
                            break;
                        case SCROLL_STATE_FLING:
                            //手指抛动时,即手指用力滑动
                            //在离开后ListView由于惯性继续滑动
    
                            /**
                             * 当用户没有做手指抛动的状态时,这个方法只会回调2次,否则会回调3次,差别就是手指抛动的这个状态。
                             * 通常情况下,我们会在这个方法中通过不同的状态来设置一些标志Flag,来区分不同的滑动状态,供其他方法处理。
                             */
                            Log.d("Test", "SCROLL_STATE_FLING");
                            break;
                    }
                }
    
                /**
                 *
                 * @param absListView
                 * @param firstVisibleItem 当前能看见的第一个Item的ID(从0开始)
                 * @param visibleItemCount 当前能看见的Item总数
                 *                         这里需要注意的是,当前能看见的Item数,包括没有显示完整的Item,即显示一小半的Item也包括在内了。
                 *
                 * @param totolItemCount 整个ListViewI 的item总数
                 */
                @Override
                public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totolItemCount) {
                    //滚动时一直调用
    
                    /**
                     * 判断当前是否滚动到最后一行
                     */
                    if(firstVisibleItem + visibleItemCount == totolItemCount
                            && totolItemCount > 0){
                        //滚动到最后一行
                        Log.d("Test", "滚动到最后一行");
                    }
    
                    /**
                     * 判断滚动的方向
                     */
                    if(firstVisibleItem > lastVisibleItemPosition){
                        //上滑
                        Log.d("Test", "上滑");
                    }else if(firstVisibleItem < lastVisibleItemPosition){
                        //下滑 Log.d("Test", "下滑");
                    }
                    lastVisibleItemPosition = firstVisibleItem;
    
                    Log.d("Test", "onScroll");
                }
            });



  3. ListView常用拓展

    具有弹性的ListView:

    Android默认的ListView在滚动到顶端或者底端的时候,并没有很好的提示。

    在Android5.X中,添加了一个半月形的阴影效果。 滚动到顶部和底部继续往上或者往下滑动一段距离。

     ListView的源代码有这么一个方法: 有个 maxOverScrollY,默认值是0,只需要修改这个参数的值,就可以让ListView具有弹性了!
    /**
         * 控制滑动到边缘的处理方法
         * @param deltaX
         * @param deltaY
         * @param scrollX
         * @param scrollY
         * @param scrollRangeX
         * @param scrollRangeY
         * @param maxOverScrollX
         * @param maxOverScrollY
         * @param isTouchEvent
         * @return
         */
        @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, maxOverScrollY,
                    isTouchEvent);
        }


    修改后的方法:

    public class MListView extends ListView {
    
        int mMaxOverDistance = (int)getResources().getDisplayMetrics().density*50;
    
        public MListView(Context context) {
            super(context);
        }
    
        public MListView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public MListView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        /**
         * 控制滑动到边缘的处理方法
         * @param deltaX
         * @param deltaY
         * @param scrollX
         * @param scrollY
         * @param scrollRangeX
         * @param scrollRangeY
         * @param maxOverScrollX
         * @param maxOverScrollY
         * @param isTouchEvent
         * @return
         */
        @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, maxOverScrollY,
    //                isTouchEvent);
    
            return super.overScrollBy(deltaX, deltaY,
                    scrollX, scrollY,
                    scrollRangeX, scrollRangeY,
                    maxOverScrollX, mMaxOverDistance,
                    isTouchEvent);
        }
    
    }



    就可以看到明显的弹性效果了!!!


    ListView + ToolBar

    ListView 向下滑动时,隐藏ToolBar,

    向上滑动时,显示ToolBar功能

    代码如下:
    public class ListViewWithTopShowOrHide extends Activity{
    
        private MListView mListView;
        private float mFirstY;
        private float mCurrentY;
        private float mTouchSlop;
        private int direction;//标识方向
        private boolean mShow = true;
        private List<String> datas = new ArrayList<String>();
        private ArrayAdapter adapter;
        private Context context;
        private ObjectAnimator animator;
        private Toolbar mToolbar;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_list_view_with_top_show_or_hide);
            context = this;
    
            mToolbar = (Toolbar)findViewById(R.id.mToolbar);
    
            mListView = (MListView)findViewById(R.id.mListView);
    
            //添加头部
            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)));
    
            mListView.addHeaderView(header);
            mListView.setOnTouchListener(myTouchListener);
    
            adapter = new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, datas);
            mListView.setAdapter(adapter);
    
            /**
             * 获取系统认为的最低滑动距离
             */
            mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
    
            initData();
        }
    
        /**
         * 加载数据
         */
        private void initData(){
            for(int i=0;i<20;i++){
                datas.add("item"+i);
            }
            adapter.notifyDataSetChanged();
    
        }
    
        private View.OnTouchListener myTouchListener = new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        //触摸时操作
                        mFirstY = event.getY();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        mCurrentY = event.getY();
                        if(mCurrentY - mFirstY > mTouchSlop){
                            direction = 0;//down
                        }else if(mFirstY - mCurrentY > mTouchSlop){
                            direction = 1;//up
                        }
                        if(direction == 1){//向上
                            Log.d("mShow", "direction: 向上滑动"+direction+" mShow:"+mShow);
                            if(mShow){
                                mShow = !mShow;
                                toolbarAnim(mShow);//隐藏
                            }
                        }else if(direction == 0){//向下
                            Log.d("mShow", "direction:向下滑动"+direction+" mShow:"+mShow);
                            if(!mShow){
                                mShow = !mShow;
                                toolbarAnim(mShow);//显示
                            }
                        }
                        //移动时操作
                        break;
                    case MotionEvent.ACTION_UP:
                        //离开时操作
                        break;
                }
                return false;
            }
        };
    
        /**
         * 是否显示toolbar
         * @param isshow
         */
        private void toolbarAnim(boolean isshow){
            if(animator!=null && animator.isRunning()){
                animator.cancel();
            }
    
    
            if(isshow){
                //显示
                animator = ObjectAnimator.ofFloat(mToolbar, "translationY", mToolbar.getTranslationY(), 0);
            }else {
                //隐藏
                animator = ObjectAnimator.ofFloat(mToolbar, "translationY", mToolbar.getTranslationY(), -mToolbar.getHeight());
            }
            animator.start();
    
        }
    }



    布局文件如下:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    
        <com.example.mydemo.widget.MListView
            android:id="@+id/mListView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"></com.example.mydemo.widget.MListView>
        <android.support.v7.widget.Toolbar
            android:id="@+id/mToolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:title="ListViewWithToolBar"
            android:background="@android:color/holo_blue_light"
            app:titleTextColor="@color/white"></android.support.v7.widget.Toolbar>
    </RelativeLayout>

    效果如图所示:

转载于:https://my.oschina.net/gabriel1215/blog/603760

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值