下拉刷新-------
1.addHeaderView必须在setAdapter之前调用
2.将paddingTop设置一个headerView高度的负值去隐藏它
getHeight()和getMeasuredHeight()的区别:
getMeasuredHeight():获取测量完的高度,只要在onMeasure方法执行完,就可以用
它获取到宽高,在自定义控件内部多使用这个
使用view.measure(0,0)方法可以主动通知系统去测量,然后就
可以直接使用它获取宽高
getHeight():必须在onLayout方法执行完后,才能获得宽高
view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
headerView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int headerViewHeight = headerView.getHeight();
//直接可以获取宽高
}
});
3.setSelection(position);将对应位置的item放置到屏幕顶端
4. 有时listview在滑动的时候背景会变黑,这是Listview默认的背景色 可以将其默认背景色改成白色的 android:cacheColorHint="#fff"
其中headerView的布局文件
<?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="wrap_content" android:gravity="center_horizontal" android:orientation="horizontal" > <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="10dp" android:layout_marginTop="10dp" > <ImageView android:id="@+id/iv_arrow" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/indicator_arrow" android:contentDescription="@null" /> <ProgressBar android:id="@+id/pb_rotate" android:layout_width="30dp" android:layout_height="30dp" android:visibility="invisible" android:layout_centerInParent="true" android:indeterminateDrawable="@drawable/indeterminate_drawable" android:indeterminateDuration="2000" /> </RelativeLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="10dp" android:layout_marginLeft="15dp" android:layout_marginTop="10dp" android:gravity="center" android:orientation="vertical" > <TextView android:id="@+id/tv_state" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下拉刷新" android:textColor="#aa000000" android:textSize="20sp" /> <TextView android:id="@+id/tv_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="最后刷新:" android:textColor="@android:color/darker_gray" android:textSize="14sp" /> </LinearLayout> </LinearLayout>
其中footerView的布局文件
<?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="wrap_content" android:gravity="center" android:orientation="horizontal" > <ProgressBar android:layout_width="30dp" android:layout_height="30dp" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:indeterminate="true" android:indeterminateDrawable="@drawable/indeterminate_drawable" android:indeterminateDuration="1000" /> <TextView android:layout_width="wrap_content" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:layout_height="wrap_content" android:textColor="#aa000000" android:layout_marginLeft="15dp" android:textSize="20sp" android:text="加载更多..."/> </LinearLayout>
android:indeterminateDrawable="@drawable/indeterminate_drawable"
<?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="0" android:pivotX="50%" android:pivotY="50%" android:drawable="@drawable/indicate_rotate" android:toDegrees="360"> </rotate>
RefreshListView的主代码
package com.demo.pullrefresh.view; import java.text.SimpleDateFormat; import java.util.Date; import com.demo.pullrefresh.R; import android.annotation.SuppressLint; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.animation.RotateAnimation; import android.widget.AbsListView; import android.widget.ImageView; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.AbsListView.OnScrollListener; public class RefreshListView extends ListView implements OnScrollListener { private View headerView;// headerView private ImageView iv_arrow; private ProgressBar pb_rotate; private TextView tv_state, tv_time; private int downY;// 按下时y的坐标 private int headerViewHeight;// headerView高 private View footerView; private int footerViewHeight; private final int PULL_REFRESH = 0;// 下拉刷新的状态 private final int RELEASE_REFRESH = 1;// 松开刷新的状态 private final int REFRESHING = 2;// 正在刷新的状态 private int currentState = PULL_REFRESH;// headerView的默认位置 private RotateAnimation upAnimation, downAnimation; private boolean isLoadingMore = false;// 当前是否正在处于加载更多 public RefreshListView(Context context) { super(context); init(); } public RefreshListView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { setOnScrollListener(this); initHeaderView(); initFooterView(); initRotateAnimation(); } /** * 初始化headerView */ private void initHeaderView() { headerView = View.inflate(getContext(), R.layout.layout_header, null); // headerView // =LayoutInflater.from(getContext()).inflate(R.layout.layout_header, // null); iv_arrow = (ImageView) headerView.findViewById(R.id.iv_arrow); pb_rotate = (ProgressBar) headerView.findViewById(R.id.pb_rotate); tv_state = (TextView) headerView.findViewById(R.id.tv_state); tv_time = (TextView) headerView.findViewById(R.id.tv_time); // 第一种方法 // headerView.getViewTreeObserver().addOnGlobalLayoutListener(new // OnGlobalLayoutListener() { // @Override // public void onGlobalLayout() { // headerView.getViewTreeObserver().removeGlobalOnLayoutListener(this); // int headerViewHeight = headerView.getHeight(); // // // Log.e("MainActivity", "headerViewHeight: "+headerViewHeight); // headerView.setPadding(0, -headerViewHeight, 0, 0); // refreshListView.addHeaderView(headerView);// // } // }); // 第二种方法 headerView.measure(0, 0);// 主动通知系统去测量 headerViewHeight = headerView.getMeasuredHeight(); Log.e("MainActivity", "headerViewHeight: " + headerViewHeight); headerView.setPadding(0, -headerViewHeight, 0, 0); addHeaderView(headerView);// } /** * 初始化旋转动画 */ private void initRotateAnimation() { upAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); upAnimation.setDuration(300); upAnimation.setFillAfter(true); downAnimation = new RotateAnimation(-180, -360, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); downAnimation.setDuration(300); downAnimation.setFillAfter(true); } /** * 初始化footerView */ private void initFooterView() { footerView = View.inflate(getContext(), R.layout.layout_footer, null); footerView.measure(0, 0);// 主动通知系统去测量该View footerViewHeight = footerView.getMeasuredHeight(); footerView.setPadding(0, -footerViewHeight, 0, 0); addFooterView(footerView); } @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: downY = (int) ev.getY(); break; case MotionEvent.ACTION_MOVE: int deltaY = (int) (ev.getY() - downY); int paddingTop = -headerViewHeight + deltaY; if (paddingTop > -headerViewHeight && getFirstVisiblePosition() == 0) { headerView.setPadding(0, paddingTop, 0, 0); Log.d("jiejie", "paddingtop" + paddingTop); if (paddingTop >= 0 && currentState == PULL_REFRESH) { // 从下拉刷新进入松开刷新的状态 currentState = RELEASE_REFRESH; refreshHeaderView(); } else if (paddingTop < 0 && currentState == RELEASE_REFRESH) { // 进入下拉刷新的状态 currentState = PULL_REFRESH; refreshHeaderView(); } return true;// 拦截TouchMove,不让ListView处理该次move事件,不过会造成ListView无法滑动 } break; case MotionEvent.ACTION_UP: if (currentState == PULL_REFRESH) { // 隐藏headerView headerView.setPadding(0, -headerViewHeight, 0, 0); } else if (currentState == RELEASE_REFRESH) { headerView.setPadding(0, 0, 0, 0); currentState = REFRESHING; refreshHeaderView(); if (listener != null) { listener.onPullRefersh(); } } break; } return super.onTouchEvent(ev); } /** * 根据currentState来更新headerView */ private void refreshHeaderView() { switch (currentState) { case PULL_REFRESH: tv_state.setText("下拉刷新"); iv_arrow.startAnimation(downAnimation); break; case RELEASE_REFRESH: tv_state.setText("松开刷新"); iv_arrow.startAnimation(upAnimation); break; case REFRESHING: iv_arrow.clearAnimation();// 因为向上的旋转动画有可能没有执行完 iv_arrow.setVisibility(View.INVISIBLE); pb_rotate.setVisibility(View.VISIBLE); tv_state.setText("正在刷新..."); break; } } /** * 完成刷新操作,重置状态,在你获取完数据并更新完adater之后,去在UI线程中调用该方法 */ public void completeRefresh() { if (isLoadingMore) { // 重置footerView状态 footerView.setPadding(0, -footerViewHeight, 0, 0); isLoadingMore = false; } else { // 重置headerView状态 headerView.setPadding(0, -headerViewHeight, 0, 0); currentState = PULL_REFRESH; pb_rotate.setVisibility(View.INVISIBLE); iv_arrow.setVisibility(View.VISIBLE); tv_state.setText("下拉刷新"); tv_time.setText("最后刷新:" + getCurrentTime()); } } /** * 取得当前系统的时间,并格式化 */ @SuppressLint("SimpleDateFormat") private String getCurrentTime() { SimpleDateFormat format = new SimpleDateFormat("yy-MM-dd HH:mm:ss"); return format.format(new Date()); } private OnRefreshListener listener; public void setOnRefreshListener(OnRefreshListener listener) { this.listener = listener; } public interface OnRefreshListener { void onPullRefersh(); void onLoadingMore(); } /** * SCROLL_STATE_IDLE:闲置状态,就是手指松开 SCROLL_STATE_TOUCH_SCROLL:手指触摸滑动,就是按着来滑动 * SCROLL_STATE_FLING:快速滑动后松开 */ @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // TODO Auto-generated method stub } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (scrollState == OnScrollListener.SCROLL_STATE_IDLE && getLastVisiblePosition() == (getCount() - 1) && !isLoadingMore) { isLoadingMore = true; footerView.setPadding(0, 0, 0, 0);// 显示footerView setSelection(getCount());// 让ListView的最后一条显示出来 if (listener != null) { listener.onLoadingMore(); } } } }
MainActivity的主代码
package com.demo.pullrefresh; import java.util.ArrayList; import java.util.List; import com.demo.pullrefresh.view.RefreshListView; import com.demo.pullrefresh.view.RefreshListView.OnRefreshListener; import android.annotation.SuppressLint; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.SystemClock; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity implements OnItemClickListener { private RefreshListView refreshListView; private MyAdapter adapter; private List<String> list ; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); initView(); initData(); } private void initView() { // TODO Auto-generated method stub // requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.mainactivity); refreshListView = (RefreshListView) findViewById(R.id.rf_mainlistview); } private void initData() { list = new ArrayList<String>(); for (int i = 0; i < 30; i++) { list.add("ListView原来的数据—— " + i); } adapter = new MyAdapter(); refreshListView.setAdapter(adapter); refreshListView.setOnRefreshListener(new OnRefreshListener() { @Override public void onPullRefersh() { // TODO Auto-generated method stub // 需要联网请求服务器的数据,然后更新UI requestDataFromServer(false); } @Override public void onLoadingMore() { // TODO Auto-generated method stub requestDataFromServer(true); } }); refreshListView.setOnItemClickListener(this); } @SuppressLint("HandlerLeak") private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { // 跟新UI adapter.notifyDataSetChanged(); refreshListView.completeRefresh(); } }; /** * 模拟向服务器请求数据 * * @param isLoadingMore */ private void requestDataFromServer(final boolean isLoadingMore) { new Thread() { public void run() { SystemClock.sleep(3000);// 模拟请求服务器的一个时间长度 Log.d("jiejie", isLoadingMore + ""); if (isLoadingMore) { list.add("加载了更多的数据 ————1"); list.add("加载了更多的数据 ————2"); list.add("加载了更多的数据 ————3"); } else { } handler.sendEmptyMessage(0); }; }.start(); } @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, "第" + arg2 + "个条目== " + list.get(arg2-1), Toast.LENGTH_SHORT).show(); } private class MyAdapter extends BaseAdapter { @Override public int getCount() { // TODO Auto-generated method stub return list.size(); } @Override public Object getItem(int arg0) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int arg0) { // TODO Auto-generated method stub return 0; } @Override public View getView(int arg0, View arg1, ViewGroup arg2) { // TODO Auto-generated method stub TextView textView = new TextView(MainActivity.this); textView.setPadding(20, 20, 20, 20); textView.setTextSize(18); textView.setText(list.get(arg0)); return textView; } } }
下面的listview是用PullToRefreshListView 框架来完成的页可以借鉴下
我是用xutils来进行网络的请求 Gson进行解析的
1 package com.it.hello.activity.fragment; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import org.xutils.x; 7 import org.xutils.common.Callback; 8 import org.xutils.http.RequestParams; 9 10 import com.google.gson.Gson; 11 import com.google.gson.JsonArray; 12 import com.google.gson.JsonElement; 13 import com.google.gson.JsonObject; 14 import com.google.gson.JsonParser; 15 import com.handmark.pulltorefresh.library.PullToRefreshBase; 16 import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode; 17 import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener2; 18 import com.handmark.pulltorefresh.library.PullToRefreshListView; 19 import com.it.hello.R; 20 import com.it.hello.activity.entity.MsgContent; 21 22 import android.os.Bundle; 23 import android.support.v4.app.Fragment; 24 import android.util.Log; 25 import android.view.LayoutInflater; 26 import android.view.View; 27 import android.view.ViewGroup; 28 import android.widget.BaseAdapter; 29 import android.widget.ListView; 30 import android.widget.TextView; 31 32 /** 33 * 短信的接受 主要实现的是ListView的上拉刷新和下拉加载 34 * 35 * @author Administrator 36 * 37 */ 38 public class MTwoFragment extends Fragment { 39 40 private String urlString = "http://111.39.245.157:9527/cmppbs/getCmpp30DeliverList.action"; 41 private PullToRefreshListView mPullToRefreshListView; 42 private BaseAdapter adapter; 43 private int page = 0; 44 private List<MsgContent> list = new ArrayList<MsgContent>(); 45 46 @Override 47 public View onCreateView(LayoutInflater inflater, ViewGroup container, 48 Bundle savedInstanceState) { 49 // TODO Auto-generated method stub 50 return inflater.inflate(R.layout.mtwofragment, container, false); 51 } 52 53 @Override 54 public void onActivityCreated(Bundle savedInstanceState) { 55 // TODO Auto-generated method stub 56 super.onActivityCreated(savedInstanceState); 57 setView(); 58 } 59 60 private void setView() { 61 // TODO Auto-generated method stub 62 mPullToRefreshListView = (PullToRefreshListView) getActivity() 63 .findViewById(R.id.lv_msg_recieve); 64 mPullToRefreshListView.setMode(Mode.BOTH); 65 ListView listView = mPullToRefreshListView.getRefreshableView(); 66 // adapter.notifyDataSetChanged(); 67 page = 1; 68 getAppHttp(page); 69 OnRefreshListener2<ListView> mListener2 = new OnRefreshListener2<ListView>() { 70 71 @Override 72 public void onPullDownToRefresh( 73 PullToRefreshBase<ListView> refreshView) { 74 // TODO Auto-generated method stub 75 list.clear(); 76 adapter.notifyDataSetChanged(); 77 page = 1; 78 getAppHttp(page); 79 } 80 81 @Override 82 public void onPullUpToRefresh( 83 PullToRefreshBase<ListView> refreshView) { 84 // TODO Auto-generated method stub 85 page++; 86 getAppHttp(page); 87 } 88 }; 89 mPullToRefreshListView.setOnRefreshListener(mListener2); 90 adapter = new Msg(); 91 listView.setAdapter(adapter); 92 } 93 94 private void getAppHttp(int page2) { 95 // TODO Auto-generated method stub 96 RequestParams params = new RequestParams(urlString); 97 params.addBodyParameter("page", page2 + ""); 98 params.addBodyParameter("rows", "5"); 99 params.addBodyParameter("order", "desc"); 100 x.http().get(params, new Callback.CommonCallback<String>() { 101 102 @Override 103 public void onCancelled(CancelledException arg0) { 104 // TODO Auto-generated method stub 105 106 } 107 108 @Override 109 public void onError(Throwable arg0, boolean arg1) { 110 // TODO Auto-generated method stub 111 112 } 113 114 @Override 115 public void onFinished() { 116 // TODO Auto-generated method stub 117 118 } 119 120 @Override 121 public void onSuccess(String arg0) { 122 // TODO Auto-generated method stub 123 Log.d("jiejie", arg0); 124 if (arg0 != null) { 125 // 1 获取解析者 126 JsonParser parser = new JsonParser(); 127 // 2 获取根节点 128 JsonElement element = parser.parse(arg0); 129 // 根据文档判断根节点属于什么类型的Gson节点对象 130 JsonObject root = element.getAsJsonObject(); 131 // 获取节点下的某个节点的value 132 JsonArray array = root.getAsJsonArray("rows"); 133 for (JsonElement obj : array) { 134 list.add(new Gson().fromJson(obj, MsgContent.class)); 135 } 136 System.out.println(list.get(0).getMsgContent()); 137 adapter.notifyDataSetChanged(); 138 mPullToRefreshListView.onRefreshComplete(); 139 } 140 } 141 }); 142 } 143 144 /** 145 * 短信接受的适配器 146 * 147 * @author Administrator 148 * 149 */ 150 private class Msg extends BaseAdapter { 151 152 @Override 153 public int getCount() { 154 // TODO Auto-generated method stub 155 if (list != null) { 156 return list.size(); 157 } else { 158 return 0; 159 } 160 } 161 162 @Override 163 public Object getItem(int arg0) { 164 // TODO Auto-generated method stub 165 return list.get(arg0); 166 } 167 168 @Override 169 public long getItemId(int arg0) { 170 // TODO Auto-generated method stub 171 return arg0; 172 } 173 174 @Override 175 public View getView(int arg0, View arg1, ViewGroup arg2) { 176 // TODO Auto-generated method stub 177 ViewHolder holder = null; 178 if (arg1 == null) { 179 holder = new ViewHolder(); 180 arg1 = View.inflate(getActivity(), R.layout.item_msgcontent, 181 null); 182 holder.textView = (TextView) arg1.findViewById(R.id.msg_phones); 183 holder.textView7 = (TextView) arg1.findViewById(R.id.moDates); 184 holder.textView3 = (TextView) arg1 185 .findViewById(R.id.msgLengths); 186 holder.textView4 = (TextView) arg1.findViewById(R.id.msgFmts); 187 holder.textView5 = (TextView) arg1 188 .findViewById(R.id.registeredDeliverys); 189 holder.textView6 = (TextView) arg1 190 .findViewById(R.id.msgContents); 191 arg1.setTag(holder); 192 } else { 193 holder = (ViewHolder) arg1.getTag(); 194 } 195 MsgContent msgContent = list.get(arg0); 196 holder.textView7.setText(msgContent.getMoDate()); 197 holder.textView3.setText("短信长度 : " + msgContent.getMsgLength()); 198 holder.textView4.setText("信息格式: " + msgContent.getMsgFmt()); 199 int ddString = msgContent.getRegisteredDelivery(); 200 if (ddString == 0) { 201 holder.textView5.setText("状态报告: " + " 不需要"); 202 } else { 203 holder.textView5.setText("状态报告: " + " 需要"); 204 } 205 holder.textView6.setText("短信内容: " + msgContent.getMsgContent()); 206 return arg1; 207 } 208 209 } 210 211 static class ViewHolder { 212 TextView textView; 213 TextView textView2; 214 TextView textView3; 215 TextView textView4; 216 TextView textView5; 217 TextView textView6; 218 TextView textView7; 219 } 220 }