zl程序教程

您现在的位置是:首页 >  移动开发

当前栏目

android上拉下拉加载更多数据

Android数据 加载
2023-09-14 08:58:19 时间
最近项目中用到了ListView的下拉刷新的功能,总结了一下前辈们的代码,单独抽取出来写了一个demo作为示例。 p br /p p 效果图 /p p 下拉刷新: /p p img src= http://img.blog.csdn.net/20130625115351921?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZX
import android.view.animation.LinearInterpolator;   import android.view.animation.RotateAnimation;   import android.widget.AbsListView;   import android.widget.AbsListView.OnScrollListener;   import android.widget.BaseAdapter;   import android.widget.ImageView;   import android.widget.LinearLayout;   import android.widget.ListView;   import android.widget.ProgressBar;   import android.widget.TextView;    * ListView下拉刷新   */   public class CustomListView extends ListView implements OnScrollListener {       private final static int RELEASE_To_REFRESH = 0;       private final static int PULL_To_REFRESH = 1;       private final static int REFRESHING = 2;       private final static int DONE = 3;       private final static int LOADING = 4;       // 实际的padding的距离与界面上偏移距离的比例       private final static int RATIO = 3;       private LayoutInflater inflater;       private LinearLayout headView;       private TextView tipsTextview;       private TextView lastUpdatedTextView;       private ImageView arrowImageView;       private ProgressBar progressBar;       private RotateAnimation animation;       private RotateAnimation reverseAnimation;       // 用于保证startY的值在一个完整的touch事件中只被记录一次       private boolean isRecored;       private int headContentWidth;       private int headContentHeight;       private int startY;       private int firstItemIndex;       private int state;       private boolean isBack;       private OnRefreshListener refreshListener;       private OnLoadListener loadListener;       private boolean isRefreshable;              private ProgressBar moreProgressBar;       private TextView loadMoreView;       private View moreView;       public CustomListView(Context context) {           super(context);           init(context);       }       public CustomListView(Context context, AttributeSet attrs) {           super(context, attrs);           init(context);       }       private void init(Context context) {           setCacheColorHint(context.getResources().getColor(R.color.transparent));           inflater = LayoutInflater.from(context);           headView = (LinearLayout) inflater.inflate(R.layout.head, null);           arrowImageView = (ImageView) headView.findViewById(R.id.head_arrowImageView);           arrowImageView.setMinimumWidth(70);           arrowImageView.setMinimumHeight(50);           progressBar = (ProgressBar) headView.findViewById(R.id.head_progressBar);           tipsTextview = (TextView) headView.findViewById(R.id.head_tipsTextView);           lastUpdatedTextView = (TextView) headView.findViewById(R.id.head_lastUpdatedTextView);           measureView(headView);           headContentHeight = headView.getMeasuredHeight();           headContentWidth = headView.getMeasuredWidth();           headView.setPadding(0, -1 * headContentHeight, 0, 0);           headView.invalidate();           Log.v("size", "width:" + headContentWidth + " height:" + headContentHeight);           addHeaderView(headView, null, false);           setOnScrollListener(this);           animation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);           animation.setInterpolator(new LinearInterpolator());           animation.setDuration(250);           animation.setFillAfter(true);           reverseAnimation = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);           reverseAnimation.setInterpolator(new LinearInterpolator());           reverseAnimation.setDuration(200);           reverseAnimation.setFillAfter(true);           state = DONE;           isRefreshable = false;                      moreView = LayoutInflater.from(context).inflate(R.layout.listfooter_more, null);           moreView.setVisibility(View.VISIBLE);           moreProgressBar = (ProgressBar) moreView.findViewById(R.id.pull_to_refresh_progress);           loadMoreView = (TextView) moreView.findViewById(R.id.load_more);           moreView.setOnClickListener(new View.OnClickListener() {                              @Override               public void onClick(View v) {                   onLoad();               }           });           addFooterView(moreView);       }       public void onScroll(AbsListView arg0, int firstVisiableItem, int arg2, int arg3) {           firstItemIndex = firstVisiableItem;       }       public void onScrollStateChanged(AbsListView arg0, int arg1) {                  }       public boolean onTouchEvent(MotionEvent event) {           if (isRefreshable) {               switch (event.getAction()) {               case MotionEvent.ACTION_DOWN:                   if (firstItemIndex == 0   !isRecored) {                       isRecored = true;                       startY = (int) event.getY();                   }                   break;               case MotionEvent.ACTION_UP:                   if (state != REFRESHING   state != LOADING) {                       if (state == DONE) {                                                  }                       if (state == PULL_To_REFRESH) {                           state = DONE;                           changeHeaderViewByState();                       }                       if (state == RELEASE_To_REFRESH) {                           state = REFRESHING;                           changeHeaderViewByState();                           onRefresh();                       }                   }                   isRecored = false;                   isBack = false;                   break;               case MotionEvent.ACTION_MOVE:                   int tempY = (int) event.getY();                   if (!isRecored   firstItemIndex == 0) {                       isRecored = true;                       startY = tempY;                   }                   if (state != REFRESHING   isRecored   state != LOADING) {                       // 保证在设置padding的过程中,当前的位置一直是在head,否则如果当列表超出屏幕的话,当在上推的时候,列表会同时进行滚动                       // 可以松手去刷新了                       if (state == RELEASE_To_REFRESH) {                           setSelection(0);                           // 往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步                           if (((tempY - startY) / RATIO   headContentHeight)   (tempY - startY)   0) {                               state = PULL_To_REFRESH;                               changeHeaderViewByState();                           }                           // 一下子推到顶了                           else if (tempY - startY  = 0) {                               state = DONE;                               changeHeaderViewByState();                           }                           // 往下拉了,或者还没有上推到屏幕顶部掩盖head的地步                       }                       // 还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态                       if (state == PULL_To_REFRESH) {                           setSelection(0);                           // 下拉到可以进入RELEASE_TO_REFRESH的状态                           if ((tempY - startY) / RATIO  = headContentHeight) {                               state = RELEASE_To_REFRESH;                               isBack = true;                               changeHeaderViewByState();                           }                           else if (tempY - startY  = 0) {                               state = DONE;                               changeHeaderViewByState();                           }                       }                       if (state == DONE) {                           if (tempY - startY   0) {                               state = PULL_To_REFRESH;                               changeHeaderViewByState();                           }                       }                       if (state == PULL_To_REFRESH) {                           headView.setPadding(0, -1 * headContentHeight + (tempY - startY) / RATIO, 0, 0);                       }                       if (state == RELEASE_To_REFRESH) {                           headView.setPadding(0, (tempY - startY) / RATIO - headContentHeight, 0, 0);                       }                   }                   break;               }           }           return super.onTouchEvent(event);       }       // 当状态改变时候,调用该方法,以更新界面       private void changeHeaderViewByState() {           switch (state) {           case RELEASE_To_REFRESH:               arrowImageView.setVisibility(View.VISIBLE);               progressBar.setVisibility(View.GONE);               tipsTextview.setVisibility(View.VISIBLE);               lastUpdatedTextView.setVisibility(View.VISIBLE);               arrowImageView.clearAnimation();               arrowImageView.startAnimation(animation);               tipsTextview.setText("松开刷新");               break;           case PULL_To_REFRESH:               progressBar.setVisibility(View.GONE);               tipsTextview.setVisibility(View.VISIBLE);               lastUpdatedTextView.setVisibility(View.VISIBLE);               arrowImageView.clearAnimation();               arrowImageView.setVisibility(View.VISIBLE);               // 是由RELEASE_To_REFRESH状态转变来的               if (isBack) {                   isBack = false;                   arrowImageView.clearAnimation();                   arrowImageView.startAnimation(reverseAnimation);                   tipsTextview.setText("下拉刷新");               } else {                   tipsTextview.setText("下拉刷新");               }               break;           case REFRESHING:               headView.setPadding(0, 0, 0, 0);               progressBar.setVisibility(View.VISIBLE);               arrowImageView.clearAnimation();               arrowImageView.setVisibility(View.GONE);               tipsTextview.setText("正在刷新...");               lastUpdatedTextView.setVisibility(View.VISIBLE);               break;           case DONE:               headView.setPadding(0, -1 * headContentHeight, 0, 0);               progressBar.setVisibility(View.GONE);               arrowImageView.clearAnimation();               arrowImageView.setImageResource(R.drawable.arrow);               tipsTextview.setText("下拉刷新");               lastUpdatedTextView.setVisibility(View.VISIBLE);               break;           }       }       public void setonRefreshListener(OnRefreshListener refreshListener) {           this.refreshListener = refreshListener;           isRefreshable = true;       }              public void setonLoadListener(OnLoadListener loadListener) {           this.loadListener = loadListener;       }       public interface OnRefreshListener {           public void onRefresh();       }              public interface OnLoadListener {           public void onLoad();       }       @SuppressWarnings("deprecation")       public void onRefreshComplete() {           state = DONE;           lastUpdatedTextView.setText("最近更新:" + new Date().toLocaleString());           changeHeaderViewByState();       }              private void onLoad() {           if (loadListener != null) {               moreProgressBar.setVisibility(View.VISIBLE);               loadMoreView.setText(getContext().getString(R.string.load_more));               loadListener.onLoad();           }       }              public void onLoadComplete() {   //      moreView.setVisibility(View.GONE);           moreProgressBar.setVisibility(View.GONE);           loadMoreView.setText(getContext().getString(R.string.more_data));       }       private void onRefresh() {           if (refreshListener != null) {               refreshListener.onRefresh();           }       }       private void measureView(View child) {           ViewGroup.LayoutParams p = child.getLayoutParams();           if (p == null) {               p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);           }           int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);           int lpHeight = p.height;           int childHeightSpec;           if (lpHeight   0) {               childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);           } else {               childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);           }           child.measure(childWidthSpec, childHeightSpec);       }       @SuppressWarnings("deprecation")       public void setAdapter(BaseAdapter adapter) {           lastUpdatedTextView.setText("最近更新:" + new Date().toLocaleString());           super.setAdapter(adapter);       }  


在 CustomListView 中有2个回调接口,OnRefreshListener 和 OnLoadListener ,分别对应 下拉和点击加载更多 时候的回调函数。在下拉刷新完成之后要调用 mListView.onRefreshComplete(); 来隐藏掉 头部,调用 mListView.onLoadComplete(); 隐藏掉 底部的加载view。


header.xml


LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"       android:layout_width="fill_parent"       android:layout_height="wrap_content"          !-- 内容 --         RelativeLayout           android:id="@+id/head_contentLayout"           android:layout_width="fill_parent"           android:layout_height="wrap_content"           android:paddingLeft="30dp"              !-- 箭头图像、进度条 --             FrameLayout               android:layout_width="wrap_content"               android:layout_height="wrap_content"               android:layout_alignParentLeft="true"               android:layout_centerVertical="true"                  !-- 箭头 --                 ImageView                   android:id="@+id/head_arrowImageView"                   android:layout_width="wrap_content"                   android:layout_height="wrap_content"                   android:layout_gravity="center"                   android:contentDescription="@string/app_name"                   android:src="@drawable/arrow" /                 !-- 进度条 --                 ProgressBar                   android:id="@+id/head_progressBar"                                      android:layout_width="wrap_content"                   android:layout_height="wrap_content"                   android:layout_gravity="center"                   android:indeterminateDrawable="@drawable/progressbar_bg"                   android:visibility="gone" /             /FrameLayout             !-- 提示、最近更新 --             LinearLayout               android:layout_width="wrap_content"               android:layout_height="wrap_content"               android:layout_centerHorizontal="true"               android:gravity="center_horizontal"               android:orientation="vertical"                  !-- 提示 --                 TextView                   android:id="@+id/head_tipsTextView"                   android:layout_width="wrap_content"                   android:layout_height="wrap_content"                   android:text="@string/pull_to_refresh_pull_label"                   android:textColor="@color/pull_refresh_textview"                   android:textSize="20sp" /                 !-- 最近更新 --                 TextView                   android:id="@+id/head_lastUpdatedTextView"                   android:layout_width="wrap_content"                   android:layout_height="wrap_content"                   android:text="@string/pull_to_refresh_refresh_lasttime"                   android:textColor="@color/gold"                   android:textSize="10sp" /             /LinearLayout         /RelativeLayout    /LinearLayout   
?xml version="1.0" encoding="utf-8"?    LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"       android:layout_width="fill_parent"       android:layout_height="fill_parent"       android:gravity="center_horizontal"       android:orientation="horizontal"       android:padding="15dp"                 ProgressBar           android:id="@+id/pull_to_refresh_progress"                      android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:gravity="center"           android:indeterminate="true"           android:visibility="gone"          /ProgressBar         TextView           android:id="@+id/load_more"           android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:layout_marginLeft="10.0dp"           android:gravity="center"           android:text="@string/more_data"           android:textColor="@color/black"          /TextView    /LinearLayout   
import android.widget.AdapterView;   import android.widget.AdapterView.OnItemClickListener;   import android.widget.BaseAdapter;   import android.widget.ImageView;   import android.widget.TextView;   import com.example.uitest.model.AppInfo;   import com.example.uitest.view.CustomListView;   import com.example.uitest.view.CustomListView.OnLoadListener;   import com.example.uitest.view.CustomListView.OnRefreshListener;   public class MainActivity extends Activity {              private static final String TAG = MainActivity.class.getSimpleName();       private static final int LOAD_DATA_FINISH = 10;       private static final int REFRESH_DATA_FINISH = 11;              private List AppInfo  mList = new ArrayList AppInfo        private CustomListAdapter mAdapter;       private CustomListView mListView;       private int count = 10;       private Handler handler = new Handler(){           public void handleMessage(android.os.Message msg) {               switch (msg.what) {               case REFRESH_DATA_FINISH:                                      if(mAdapter!=null){                       mAdapter.notifyDataSetChanged();                   }                   mListView.onRefreshComplete();  //下拉刷新完成                   break;               case LOAD_DATA_FINISH:                   if(mAdapter!=null){                       mAdapter.notifyDataSetChanged();                   }                   mListView.onLoadComplete(); //加载更多完成                   break;               default:                   break;               }           };       };              @Override       protected void onCreate(Bundle savedInstanceState) {           super.onCreate(savedInstanceState);           setContentView(R.layout.activity_main);                      buildAppData();                      mAdapter = new CustomListAdapter(this);           mListView = (CustomListView) findViewById(R.id.mListView);           mListView.setAdapter(mAdapter);                      mListView.setonRefreshListener(new OnRefreshListener() {                              @Override               public void onRefresh() {                   //TODO 下拉刷新                   Log.e(TAG, "onRefresh");                   loadData(0);               }           });                      mListView.setonLoadListener(new OnLoadListener() {                              @Override               public void onLoad() {                   //TODO 加载更多                   Log.e(TAG, "onLoad");                   loadData(1);               }           });                      mListView.setOnItemClickListener(new OnItemClickListener() {               @Override               public void onItemClick(AdapterView ?  parent, View view,                       int position, long id) {                   Log.e(TAG, "click position:" + position);               }           });       }              public void loadData(final int type){           new Thread(){               @Override               public void run() {                                      for(int i=count;i count+10;i++){                       AppInfo ai = new AppInfo();                       ai.setAppIcon(BitmapFactory.decodeResource(getResources(),                               R.drawable.ic_launcher));                       ai.setAppName("应用Demo_" + i);                       ai.setAppVer("版本: " + (i % 10 + 1) + "." + (i % 8 + 2) + "."                               + (i % 6 + 3));                       ai.setAppSize("大小: " + i * 10 + "MB");                       mList.add(ai);                   }                   count += 10;                                      try {                       Thread.sleep(300);                   } catch (InterruptedException e) {                       e.printStackTrace();                   }                                      if(type==0){    //下拉刷新   //                  Collections.reverse(mList); //逆序                       handler.sendEmptyMessage(REFRESH_DATA_FINISH);                   }else if(type==1){                       handler.sendEmptyMessage(LOAD_DATA_FINISH);                   }                                  }           }.start();       }              /**       * 初始化应用数据       */       private void buildAppData() {           for (int i = 0; i   10; i++) {               AppInfo ai = new AppInfo();               ai.setAppIcon(BitmapFactory.decodeResource(getResources(),                       R.drawable.ic_launcher));               ai.setAppName("应用Demo_" + i);               ai.setAppVer("版本: " + (i % 10 + 1) + "." + (i % 8 + 2) + "."                       + (i % 6 + 3));               ai.setAppSize("大小: " + i * 10 + "MB");               mList.add(ai);           }       }       @Override       public boolean onCreateOptionsMenu(Menu menu) {           // Inflate the menu; this adds items to the action bar if it is present.           getMenuInflater().inflate(R.menu.main, menu);           return true;       }              public class CustomListAdapter extends BaseAdapter {           private LayoutInflater mInflater;           public CustomListAdapter(Context context) {               mInflater = LayoutInflater.from(context);           }           @Override           public int getCount() {               return mList.size();           }           @Override           public Object getItem(int arg0) {               return mList.get(arg0);           }           @Override           public long getItemId(int position) {               return position;           }           @Override           public View getView(int position, View convertView, ViewGroup parent) {               if (getCount() == 0) {                   return null;               }               ViewHolder holder = null;               if (convertView == null) {                   convertView = mInflater.inflate(R.layout.list_item, null);                   holder = new ViewHolder();                   holder.ivImage = (ImageView) convertView                           .findViewById(R.id.ivIcon);                   holder.tvName = (TextView) convertView                           .findViewById(R.id.tvName);                   holder.tvVer = (TextView) convertView.findViewById(R.id.tvVer);                   holder.tvSize = (TextView) convertView                           .findViewById(R.id.tvSize);                   convertView.setTag(holder);               } else {                   holder = (ViewHolder) convertView.getTag();               }               AppInfo ai = mList.get(position);               holder.ivImage.setImageBitmap(ai.getAppIcon());               holder.tvName.setText(ai.getAppName());               holder.tvVer.setText(ai.getAppVer());               holder.tvSize.setText(ai.getAppSize());               return convertView;           }       }       public static class ViewHolder {           private ImageView ivImage;           private TextView tvName;           private TextView tvVer;           private TextView tvSize;       }  
    xmlns:android="http://schemas.android.com/apk/res/android"       android:layout_width="match_parent"       android:layout_height="wrap_content"          ImageView           android:id="@+id/ivIcon"           android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:contentDescription="@string/image_desc"           android:src="@drawable/ic_launcher" /         LinearLayout           android:id="@+id/appInfo"           android:layout_width="match_parent"           android:layout_height="wrap_content"           android:layout_marginLeft="5dip"           android:layout_toRightOf="@id/ivIcon"           android:orientation="vertical"              TextView               android:id="@+id/tvName"               android:layout_width="wrap_content"               android:layout_height="wrap_content"               android:text="@string/name"               android:textColor="#000000"               android:textSize="16sp" /             TextView               android:id="@+id/tvVer"               android:layout_width="wrap_content"               android:layout_height="wrap_content"               android:text="@string/ver"               android:textColor="#666666"               android:textSize="13sp" /             TextView               android:id="@+id/tvSize"               android:layout_width="wrap_content"               android:layout_height="wrap_content"               android:text="@string/size"               android:textColor="#666666"               android:textSize="13sp" /         /LinearLayout         Button           android:id="@+id/btnClick"           android:layout_width="80dip"           android:layout_height="wrap_content"           android:layout_alignParentRight="true"           android:layout_centerVertical="true"           android:focusable="false"           android:text="@string/mgr"           android:textColor="#000000"           android:textSize="16sp" /    /RelativeLayout   
一文读懂系列Android屏幕刷新机制 对一些大中型项目来说可能就不一样了:**他们涉及业务较多,设备种类较多,往往一个app内部集成了十几个子业务甚至上百个,这对应用性能要求就更加严格了,app的体验也会间接导致用户的留存问题**。 所以学习屏幕绘制这类理论性较强的知识也是非常有必要的。
在不丢失数据的情况下处理屏幕旋转 - Android 我正在疯狂地弄清楚处理屏幕旋转的最佳方法是什么。 如何在重新创建活动之前保存 myClass 数据,以便我可以保留重绘活动的所有内容,而无需再次进行无用的初始化? 有没有比 Parcelable 更清洁、更好的方法? 我需要处理旋转,因为我想在横向模式下更改布局。
      小菜在适配 Android8.0 过程中,遇到很多问题,有很多很常见的问题,今天来整理一下页面跳转时黑屏的问题。       显示 Activity 页面之前会优先开启一个 Starting Window(Preview Window),等待 Activity 加载完成之后显示 UI 界面,猜测在这个等待过程中可能会出现页面跳转时的短暂黑屏。
      小菜前段时间根据超多 star 的 FlycoTabLayout 自己修改封装了仿网易顶部滑动标题栏 TabSlideLayout 滑动内容可以是文字也可以是网络图标,并整理了两篇小博客: Android 优化个人封装仿网易新闻可滑动标题...
自定义view实现 思路分析:通过canvas画圆,每次改变圆半径和透明度,当半径达到一定程度,再次从中心开始绘圆,达到不同层级...
看过我这边文章的RecyclerView.Adapter的优化与封装的真的想说声抱歉,其实不需要继承BaseBean,只需要继承Object就可以了,而且更灵活了,当时不知道咋了,脑袋抽风了,多次了这一举。