zoukankan      html  css  js  c++  java
  • Android的ListView分页功能(上滑加载更多)

      今天主要工作是将之前实现的各种ListView显示全部信息,优化成了每次加载几条数据,然后上滑的时候加载更多,底部显示一个进度条和一个文字提示,然后加载完毕后,将提示信息隐藏。

      一边看教学视频一遍敲代码,边学习边实践,感觉学到了很多东西。

      课程连接:http://www.imooc.com/learn/136

      

      好了,说说是怎么做的吧,供以后学习参考。

      首先要定义一个footer.xml作为进度条和提示加载中的底部布局,代码如下:

        <LinearLayout
            android:id="@+id/load_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal"
            android:paddingBottom="10dip"
            android:paddingTop="10dip"
            tools:ignore="UselessParent" >
    
            <ProgressBar
                style="?android:attr/progressBarStyleLargeInverse"
                android:layout_width="30dp"
                android:layout_height="30dp" />
            
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="正在加载......"
                android:textSize="16sp"
                tools:ignore="HardcodedText" />
    
        </LinearLayout>

      这样的显示效果就是这样的:

      

      然后自定义一个LoadListView,继承自ListView,实现其三个构造方法:

        public LoadListView(Context context) {
            super(context);        
            initView(context);
        }
        public LoadListView(Context context, AttributeSet attrs) {
            super(context, attrs);
            initView(context);
        }
        public LoadListView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            initView(context);
        }

      其中initView()是通过inflater初始化布局的,代码:

        private void initView(Context context){
            LayoutInflater inflater = LayoutInflater.from(context);
            footer = inflater.inflate(R.layout.footer, null);
            footer.findViewById(R.id.load_layout).setVisibility(GONE);
            this.addFooterView(footer);
            this.setOnScrollListener(this);
        }

      然后,实现实现它的滑动事件接口,(详见代码,这里只说过程),目的是为了监听ListView上滑到底部的时候,显示那个【加载更多...】提示信息,然后实现加载更多的函数运行,达到加载出更多数据。

      那么问题来了,加在了更多数据是重新设置数据适配器吗?答案当然是不可以重新设置,这里我们首先判断adapter是否为空,如果是空的,就setAdaper(),如果不是,其实就是加载更多以后,我们不去重新设置,而是调用this.notifyDataSetChanged();  //当有数据变化的时候,ListView会自动刷新界面。这样很好的保证了数据不会重新设置,效果还不错。

                if(adapter == null){
                    adapter = new FenleiAdapter(FenleiActivity.this, newsBeans);
                    mListView.setAdapter(adapter);
                }else {
                    adapter.onDateChange(newsBeans);
                }
        public void onDateChange(List<FenleiBean> mList) {
            // TODO Auto-generated method stub
            this.mList = mList;
            this.notifyDataSetChanged();  //当有数据变化的时候,自动刷新界面
            
        }

      继续,这个时候我们会遇到一个问题,就是在自定义类LoadListView中,怎么去调用MainActivity中的方法,答案是接口回调,大概的意思就是在LoadListView中定义一个接口,然后去MainActivity具体实现这个接口,调用的时候,通过ListView变量来调用,具体我也只是大致明白这个意思,如果不明白可以再百度一下。

      当ListView通过findViewById()找到控件id的时候,不要忘了将这个接口设置给ListView,代码是mListView.setInterface(this);

      最后的最后要在加载完数据之后,去把提示消息设置为隐藏,这样,整个就大功告成了!!!

      最后的效果如图:

       

            [上滑效果]                [加载更多以后的效果]

    LoadListView.java源码(具体还要根据你的项目去写)

    package com.tdyl.consult.fenlei;
    
    import com.tdyl.consult.R;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.widget.AbsListView;
    import android.widget.AbsListView.OnScrollListener;
    import android.widget.ListView;
    
    public class LoadListView extends ListView implements OnScrollListener {
    
        View footer; 
        int totalItemCount;
        int lastVisibleItem;
        boolean isLoading;
        ILoadListener2 iListener2;
        public LoadListView(Context context) {
            super(context);        
            initView(context);
        }
        public LoadListView(Context context, AttributeSet attrs) {
            super(context, attrs);
            initView(context);
        }
        public LoadListView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            initView(context);
        }
        
        private void initView(Context context){
            LayoutInflater inflater = LayoutInflater.from(context);
            footer = inflater.inflate(R.layout.footer, null);
            footer.findViewById(R.id.load_layout).setVisibility(GONE);
            this.addFooterView(footer);
            this.setOnScrollListener(this);
        }
        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            this.lastVisibleItem = firstVisibleItem + visibleItemCount;
            this.totalItemCount = totalItemCount;
        }
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollStatus) {
            if(totalItemCount == lastVisibleItem
                    && scrollStatus == SCROLL_STATE_IDLE){
                if(!isLoading){
                    isLoading = true;
                    footer.findViewById(R.id.load_layout).setVisibility(VISIBLE);
                    //加载更多数据
                    iListener2.onLoad();
                }
            }
        }
        
        public void loadComplete(){
            isLoading = false;
            footer.findViewById(R.id.load_layout).setVisibility(GONE);
        }
        
        public void setInterface(ILoadListener2 iListener2){
            this.iListener2 = iListener2;
        }
        
        public interface ILoadListener2{
            public void onLoad();
        }
    
    }
    View Code

    MainActivity.java源码(我这里叫FenleiActivity.java,道理是一样的)

    package com.tdyl.consult.fenlei;
    
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    
    import org.ksoap2.SoapEnvelope;
    import org.ksoap2.SoapFault;
    import org.ksoap2.serialization.SoapObject;
    import org.ksoap2.serialization.SoapSerializationEnvelope;
    import org.ksoap2.transport.HttpTransportSE;
    import org.xmlpull.v1.XmlPullParserException;
    
    import android.app.Activity;
    import android.app.AlertDialog;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.os.Handler;
    import android.util.Log;
    import android.view.View;
    import android.view.Window;
    import android.widget.AdapterView;
    import android.widget.AdapterView.OnItemClickListener;
    import android.widget.ListView;
    import android.widget.TextView;
    
    import com.tdyl.consult.R;
    import com.tdyl.consult.fenlei.LoadListView.ILoadListener2;
    import com.tdyl.consult.otochat.ChatOtoActivity;
    
    public class FenleiActivity extends Activity implements ILoadListener2 {
    
        private LoadListView mListView;
        private String user_fenlei = "";
        private TextView title_name;
        int number = 10;
        FenleiAdapter adapter = null;
    
        ArrayList <HashMap<String,Object>> list=new ArrayList<HashMap<String,Object>>();  //用来存放用户信息
        HashMap<String, Object> map = new HashMap<String, Object>();
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            setContentView(R.layout.activity_fenlei);
            title_name = (TextView) findViewById(R.id.id_top_fenlei);
            mListView = (LoadListView) findViewById(R.id.lv_main);
            mListView.setInterface(this);
            Intent intent = getIntent();
            user_fenlei = intent.getStringExtra("user_fenlei");
            //-----------------------------------------------------------------------------
            title_name.setText(user_fenlei+"专家");
            new NewsAsynkTask().execute(number);
        }
    
        /**
         * 将url对应的json格式数据转化为我们缩封装的NewsBean对象
         * @param url
         * @return
         */
        private List<FenleiBean> getJsonData(int number){
            List<FenleiBean> newsBeanList = new ArrayList<FenleiBean>();
            //-----------------------------------------------------------------------------
            searchTop10(number);
            FenleiBean newsBean;
            if(list.size() == 0)
            {
                new AlertDialog.Builder(this)
                .setIcon(R.drawable.icon_menu)
                .setTitle("温馨小提示")
                .setMessage("没有要搜寻的专家分类")
                .setPositiveButton("立刻返回搜索界面...", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        finish();
                    }
                }).show();
            }
            for(int i=0;i<list.size();i++)
            {
                newsBean = new FenleiBean();
                HashMap<String, Object> map1 = new HashMap<String, Object>();
                map1 = list.get(i);
                newsBean.newsIconUrl = map1.get("user_touxiangURL").toString();
                newsBean.newTitle = map1.get("username").toString();
                newsBean.newsContent = map1.get("user_qianming").toString();
                newsBean.newsJifen = map1.get("user_jifen").toString();
                newsBeanList.add(newsBean);
            }
            return newsBeanList;    
        }
    
        /**
         * 实现网络的异步访问
         * @author Lenovo
         *
         */
        class NewsAsynkTask extends AsyncTask<Integer,Void, List<FenleiBean>>{
    
            @Override
            protected List<FenleiBean> doInBackground(Integer... params) {
                return getJsonData(params[0]);
            }
    
            @Override
            protected void onPostExecute(List<FenleiBean> newsBeans) {
                // TODO Auto-generated method stub
                super.onPostExecute(newsBeans);
                if(adapter == null){
                    adapter = new FenleiAdapter(FenleiActivity.this, newsBeans);
                    mListView.setAdapter(adapter);
                }else {
                    adapter.onDateChange(newsBeans);
                }
    
                mListView.setOnItemClickListener(new OnItemClickListener() {
    
                    @Override
                    public void onItemClick(AdapterView<?> parent, View view,
                            int position, long id) {
                        // TODO Auto-generated method stub
                        HashMap<String, Object> map1 = list.get(position);
                        Intent intent=new Intent();
                        intent.setClass(FenleiActivity.this,ChatOtoActivity.class);
                        intent.putExtra("username", map1.get("username").toString());     //用户名传到另一个界面
                        System.out.println("username"+map1.get("username").toString());
                        intent.putExtra("touxiang", map1.get("user_touxiangURL").toString());    //头像地址
                        //启动
                        startActivity(intent);
    
                        //Toast.makeText(FenleiActivity.this, "点击了"+newsBean.get("username"),Toast.LENGTH_SHORT).show();
                    }
                });
            }
    
    
        }
    
        /**
         * 查询用户分类信息函数,放入list中,通过关键字key来取出
         * */
    
        public void searchTop10(int number)
        {
            //命名空间
            String nameSpace = "http://wsServer.gnuhpc.org/";
            //方法名字
            String methodName = "SearchTeacherTop10";
            // endPoint
            String endPoint =  "http://10.0.2.2:8080/wsServerHello";
            //soapAction
            String soapAction = "http://wsServer.gnuhpc.org/SearchTeacherTop10";
            //指定调用方法命名空间和方法名字
            SoapObject rpc = new SoapObject(nameSpace, methodName); 
            //调用方法时需要传入一个参数
            //为了与web service保持一致,需要设置为arg0,因为web service会自动将其转化为arg0 arg1
            rpc.addProperty("arg0",user_fenlei);
            rpc.addProperty("arg1",number);
            try {
                //wsdl地址
                HttpTransportSE transport = new HttpTransportSE(endPoint);
                transport.debug= true;
                //生成调用WebService方法的SOAP请求信息,并指定SOAP的版本 
                SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);    
                envelope.bodyOut = rpc;    
                //设置是否调用的是dotNet开发的WebService,服务器是.net的需要设置为true,java不用
                envelope.dotNet = false;                 
                envelope.setOutputSoapObject(rpc);                 
    
                System.out.println("rpc:"+rpc); 
                System.out.println("enevlope:"+envelope); 
                System.out.println("---基本服务设置完毕,下面开始调用服务");
    
                Log.v("---调用消息:", "开始call函数");
                transport.call(soapAction, envelope);
                Log.v("---函数结果:", ""+envelope.getResponse());
                if(envelope.getResponse()!=null)  
                {
                    // 获取返回的数据  
                    SoapObject object = (SoapObject) envelope.bodyIn; 
                    System.out.println("---object:"+object);
                    System.out.println("---获取数据成功!");
                    System.out.println("object.toString():"+object.toString()); 
    
                    // 获取返回的结果 ,将结果存入到一个Map中
                    System.out.println(object.getProperty(0)); 
                    int count = object.getPropertyCount();
                    System.out.println("#######################"+count);
    
                    for(int index = 0; index < count; index = index + 5)  //表中有五个关键字,循环条件+5
                    {
                        map = new HashMap<String, Object>();
                        map.put("username", object.getProperty(index).toString());  //用户名
                        map.put("user_fenlei", object.getProperty(index+1).toString());  //分类
                        map.put("user_qianming", object.getProperty(index+2).toString());  //签名
                        map.put("user_touxiangURL", object.getProperty(index+3).toString());  //在线状态
                        map.put("user_jifen", object.getProperty(index+4).toString());  //积分
                        list.add(map);
                    }
                    System.out.println("list的值为:"+list);
                }
                else{
                    Log.v("----连接消息:", "连接失败");
                }
            } catch (SoapFault e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (XmlPullParserException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void onLoad() {
            //获取更多数据
            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
    
                @Override
                public void run() {
                    number=number+2;  //每次多显示两条数据
                    new NewsAsynkTask().execute(number);
                    //通知listView显示更新,加载完毕 
                    
                    /**
                     * 设置默认显示为Listview最后一行
                     */
                    mListView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
                    mListView.setStackFromBottom(true);
                    //通知listView加载完毕,底部布局消失
                    mListView.loadComplete();
    
                }
            }, 1000);
        }
    
    }
    View Code

      感谢这门视频课程,汲取营养,继续努力......

  • 相关阅读:
    Linux systemd & init.d
    windows 气泡提示
    C++17新特性
    Lua & C++
    C++智能指针原理
    C++ Memory Order
    析命令提示符的原理
    设置与获取系统代理信息
    命令查看系统信息
    Linux shell脚本
  • 原文地址:https://www.cnblogs.com/cnyulei/p/6858625.html
Copyright © 2011-2022 走看看