ListView下拉刷新上拉加载更多实现
这篇文章将带大家了解listview下拉刷新和上拉加载更多的实现过程,先看效果(注:图片中listview中的阴影可以加上属性android:fadingEdge="none"去掉):
1
2
3
4
5
接下来再看一下工程文件;
首先,实现这种效果需要重写ListView控件,工程中的RefreshListView即继承了ListView,并实现了OnScrollListener接口,头部和脚部和主界面其实是连在一起的,只是在RefreshListView中没让它显示出来,只有当特定条件比如下拉上拉时才会显示,这些动作执行完毕后又会重新隐藏,先来看一下RefreshListView代码:
/**
* @author baiyuliang
*/
public class RefreshListView extends ListView implements OnScrollListener {
private int downY; // 按下时y轴的偏移量
private View headerView; // 头布局
private int headerViewHeight; // 头布局的高度
private int firstVisibleItemPosition; // 滚动时界面显示在顶部的item的position
private DisplayMode currentState = DisplayMode.Pull_Down; // 头布局当前的状态, 缺省值为下拉状态
private Animation upAnim,downAnim,loadAnim; // 向上旋转的动画,向下旋转的动画,刷新数据时load动画
private ImageView ivArrow; // 头布局的箭头
private TextView tvState; // 头布局刷新状态
private ImageView loading_img_header,loading_img_footer; // 头布局和脚布局的进度条
private TextView tvLastUpdateTime; // 头布局的最后刷新时间
private OnRefreshListener mOnRefreshListener;
private boolean isScroll2Bottom = false; // 是否滚动到底部
private View footerView; // 脚布局
private int footerViewHeight; // 脚布局的高度
private boolean isLoadMoving = false; // 是否正在加载更多中
public RefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
initHeader();
initFooter();
this.setOnScrollListener(this);
}
/**
* 初始化脚布局
*/
private void initFooter() {
footerView = LayoutInflater.from(getContext()).inflate(R.layout.activity_listview_refresh_footer, null);
loading_img_footer=(ImageView) footerView.findViewById(R.id.pb_listview_footer_progress);
measureView(footerView); // 测量一下脚布局的高度
footerViewHeight = footerView.getMeasuredHeight();
footerView.setPadding(0, -footerViewHeight, 0, 0); // 隐藏脚布局
this.addFooterView(footerView);
}
/**
* 初始化头布局
*/
private void initHeader() {
//头部
headerView = LayoutInflater.from(getContext()).inflate(R.layout.activity_listview_refresh_header, null);
ivArrow = (ImageView) headerView.findViewById(R.id.iv_listview_header_down_arrow);
loading_img_header = (ImageView) headerView.findViewById(R.id.pb_listview_header_progress);
tvState = (TextView) headerView.findViewById(R.id.tv_listview_header_state);
tvLastUpdateTime = (TextView) headerView.findViewById(R.id.tv_listview_header_last_update_time);
ivArrow.setMinimumWidth(50);
tvLastUpdateTime.setText("上次刷新时间: " + getLastUpdateTime());
measureView(headerView);
headerViewHeight = headerView.getMeasuredHeight();
Log.i("RefreshListView", "头布局的高度: " + headerViewHeight);
headerView.setPadding(0, -headerViewHeight, 0, 0); // 隐藏头布局
this.addHeaderView(headerView);
initAnimation();
}
/**
* 获得最后刷新的时间
* @return
*/
private String getLastUpdateTime() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(new Date());
}
/**
* 初始下拉刷新时箭头动画
*/
private void initAnimation() {
//向上
upAnim = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
upAnim.setDuration(500);
upAnim.setFillAfter(true);
//向下
downAnim = new RotateAnimation(-180, -360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
downAnim.setDuration(500);
downAnim.setFillAfter(true);
//刷新数据时load动画
loadAnim=new RotateAnimation(0, 359, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
loadAnim.setDuration(2000);
loadAnim.setInterpolator(new LinearInterpolator());
loadAnim.setFillAfter(true);
loadAnim.setRepeatCount(-1);
}
/**
* 测量给定的View的宽和高, 测量之后, 可以得到view的宽和高
* @param child
*/
private void measureView(View child) {
ViewGroup.LayoutParams lp = child.getLayoutParams();
if (lp == null) {
lp = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0, lp.width);
int lpHeight = lp.height;
int childHeightSpec;
if (lpHeight > 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
} else {
childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec, childHeightSpec);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downY = (int) ev.getY();
break;
case MotionEvent.ACTION_MOVE:
if(currentState == DisplayMode.Refreshing) {
// 当前的状态是正在刷新中, 不执行下拉操作
break;
}
int moveY = (int) ev.getY(); // 移动中的y轴的偏移量
int diffY = moveY - downY;
int paddingTop = -headerViewHeight + (diffY / 2);
if(firstVisibleItemPosition == 0&& paddingTop > -headerViewHeight) {
/**
* paddingTop > 0 完全显示
* currentState == DisplayMode.Pull_Down 当是在下拉状态时
*/
if(paddingTop > 0&& currentState == DisplayMode.Pull_Down) { // 完全显示, 进入到刷新状态
Log.i("RefreshListView", "松开刷新");
currentState = DisplayMode.Release_Refresh; // 把当前的状态改为松开刷新
refreshHeaderViewState();
} else if(paddingTop < 0&& currentState == DisplayMode.Release_Refresh) { // 没有完全显示, 进入到下拉状态
Log.i("RefreshListView", "下拉刷新");
currentState = DisplayMode.Pull_Down;
refreshHeaderViewState();
}
headerView.setPadding(0, paddingTop, 0, 0);
return true;
}
break;
case MotionEvent.ACTION_UP:
downY = -1;
if(currentState == DisplayMode.Pull_Down) { // 松开时, 当前显示的状态为下拉状态, 执行隐藏headerView的操作
headerView.setPadding(0, -headerViewHeight, 0, 0);
} else if(currentState == DisplayMode.Release_Refresh) { // 松开时, 当前显示的状态为松开刷新状态, 执行刷新的操作
headerView.setPadding(0, 0, 0, 0);
currentState = DisplayMode.Refreshing;
refreshHeaderViewState();
if(mOnRefreshListener != null) {
mOnRefreshListener.onRefresh();
}
}
break;
default:
break;
}
return super.onTouchEvent(ev);
}
/**
* 当刷新任务执行完毕时, 回调此方法, 去刷新界面
*/
public void onRefreshFinish() {
if(isLoadMoving) { // 隐藏脚布局
loading_img_footer.clearAnimation();
isLoadMoving = false;
isScroll2Bottom = false;
footerView.setPadding(0, -footerViewHeight, 0, 0);
} else { // 隐藏头布局
headerView.setPadding(0, -headerViewHeight, 0, 0);
loading_img_header.clearAnimation();
loading_img_header.setVisibility(View.GONE);
ivArrow.setVisibility(View.VISIBLE);
tvState.setText("下拉刷新");
tvLastUpdateTime.setText("上次刷新时间: " + getLastUpdateTime());
currentState = DisplayMode.Pull_Down;
}
}
/**
* 刷新头布局的状态
*/
private void refreshHeaderViewState() {
if(currentState == DisplayMode.Pull_Down) { // 当前进入下拉状态
ivArrow.startAnimation(downAnim);
tvState.setText("下拉刷新");
} else if(currentState == DisplayMode.Release_Refresh) { //当前进入松开刷新状态
ivArrow.startAnimation(upAnim);
tvState.setText("释放立即刷新");
} else if(currentState == DisplayMode.Refreshing) { //当前进入正在刷新中
ivArrow.clearAnimation();
ivArrow.setVisibility(View.GONE);
loading_img_header.setVisibility(View.VISIBLE);
loading_img_header.startAnimation(loadAnim);
tvState.setText("正在获取新内容");
}
}
/**
* 刷新头布局的状态
* 当ListView滚动状态改变时回调
* SCROLL_STATE_IDLE // 当ListView滚动停止时
* SCROLL_STATE_TOUCH_SCROLL // 当ListView触摸滚动时
* SCROLL_STATE_FLING // 快速的滚动(手指快速的触摸移动)
*/
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if(scrollState == OnScrollListener.SCROLL_STATE_IDLE || scrollState == OnScrollListener.SCROLL_STATE_FLING) {
if(isScroll2Bottom && !isLoadMoving) { // 滚动到底部
// 加载更多
loading_img_footer.startAnimation(loadAnim);
footerView.setPadding(0, 0, 0, 0);
this.setSelection(this.getCount()); // 滚动到ListView的底部
isLoadMoving = true;
if(mOnRefreshListener != null) {
mOnRefreshListener.onLoadMoring();
}
}
}
}
/**
* 当ListView滚动时触发
* firstVisibleItem 屏幕上显示的第一个Item的position
* visibleItemCount 当前屏幕显示的总个数
* totalItemCount ListView的总条数
*/
@Override
public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {
firstVisibleItemPosition = firstVisibleItem;
Log.i("RefreshListView", "onScroll: " + firstVisibleItem + ", " + visibleItemCount + ", " + totalItemCount);
if((firstVisibleItem + visibleItemCount) >= totalItemCount&& totalItemCount > 0) {
Log.i("RefreshListView", "加载更多");
isScroll2Bottom = true;
} else {
isScroll2Bottom = false;
}
}
/**
* @author andong
* 下拉头部的几种显示状态
*/
public enum DisplayMode {
Pull_Down, // 下拉刷新的状态
Release_Refresh, // 松开刷新的状态
Refreshing // 正在刷新中的状态
}
/**
* 设置刷新的监听事件
* @param listener
*/
public void setOnRefreshListener(OnRefreshListener listener) {
this.mOnRefreshListener = listener;
}
}
代码看上去比较复杂,大家可以慢慢研究,主要就是设置监听了几个动作,触摸屏幕,向下滑动,离开屏幕,下上滑动等等,根据不同动作执行相应操作,比如下拉时,头部布局便会显示出来,而当头部拉伸超过一定尺度后,箭头会执行一个动画,又指向下变为指向上,头部布局中的Textview空间内容也会发生相应变化,当松开手指时,又会出现一个动画如上图标记额地方,其实是一张图片,设置了旋转动画而已,而上拉加载更多是同样的道理,而且在动作执行完毕时,仍会有一个监听,主要是销毁动画和隐藏头部或脚部布局。
图中listview的效果是需要写一个自定义的适配器,这个我想大家都明白,也都会想到的吧,就不用我多说了,看代码:
/**
* @author baiyuliang
*/
public class MyAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<HashMap<String, String>> listDate;
private static LayoutInflater inflater=null;
public MyAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
listDate=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return listDate.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.list_item, null);
TextView username = (TextView) vi.findViewById(R.id.username); // 用户头像
TextView creatdate=(TextView) vi.findViewById(R.id.creatdate);//时间
TextView mood=(TextView) vi.findViewById(R.id.mood);//心情内容
HashMap<String, String> map = new HashMap<String, String>();
map = listDate.get(position);
//设置ListView的相关控件
username.setText(map.get("username"));
creatdate.setText(map.get("creatdate"));
mood.setText(map.get("mood"));
return vi;
}
}
接下来我们看一下,主界面main.xml布局代码:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<TextView
android:id="@+id/title"
android:layout_width="fill_parent"
android:layout_height="45dip"
android:text="下拉刷新上拉加载"
android:textColor="#FFFFFF"
android:textSize="20sp"
android:gravity="center"
android:background="@drawable/tab_footer_bg"
/>
<com.baiyuliang.pullrefresh.RefreshListView
android:id="@+id/refresh_listview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="@+id/title"/>
</RelativeLayout>
很简单,就是一个标题栏和我们重写的ListView,listview中每个条目的布局list_item布局如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFFFFF"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="50dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp" >
<RelativeLayout
android:id="@+id/headimg"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_centerVertical="true" >
<ImageView
android:id="@+id/head_img"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_centerVertical="true"
android:src="@drawable/head_img"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/name_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:layout_toRightOf="@+id/headimg" >
<TextView
android:id="@+id/username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="baiyuliang"
android:textColor="#00008B"
android:textSize="20sp" />
<TextView
android:id="@+id/creatdate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/username"
android:layout_below="@+id/username"
android:layout_marginLeft="2dp"
android:text="今天12:00"
android:textSize="12sp" />
</RelativeLayout>
</RelativeLayout>
<TextView
android:id="@+id/mood"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:text="今天心情不错,出来冒个泡!"
android:textColor="#000000"
android:textSize="15sp" />
<ImageView
android:id="@+id/mood_img"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="5dp" />
<RelativeLayout
android:id="@+id/phonetype"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp" >
<ImageView
android:id="@+id/phone_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginRight="2dp"
android:src="@drawable/phone_type" />
<TextView
android:id="@+id/phone_type_hanzi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/phone_type"
android:text="Android" />
<ImageView
android:id="@+id/zan_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="3dp"
android:layout_toLeftOf="@+id/zan_hanzi"
android:src="@drawable/qz_detail_icon_praise" />
<TextView
android:id="@+id/zan_hanzi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="2dp"
android:layout_marginRight="10dp"
android:layout_toLeftOf="@+id/pinglun_img"
android:text="赞"
android:textSize="12sp" />
<ImageView
android:id="@+id/pinglun_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="3dp"
android:layout_toLeftOf="@+id/pinglun_hanzi"
android:src="@drawable/qz_detail_icon_comment" />
<TextView
android:id="@+id/pinglun_hanzi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="评论"
android:textSize="12sp" />
</RelativeLayout>
</LinearLayout>
再看MainActivity:
/**
* @author baiyuliang
*/
public class MainActivity extends Activity {
private MyAdapter mAdapter;
private ArrayList<HashMap<String, String>> listItem;//生成动态数组,加入数据
private RefreshListView mRefreshListView;
private HashMap<String, String> map;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initView();
initData();
}
public void initView() {
mRefreshListView = (RefreshListView)findViewById(R.id.refresh_listview);
listItem = new ArrayList<HashMap<String, String>>();
}
private void initData() {
for (int i = 0; i < 10; i++) {
map=new HashMap<String, String>();
map.put("username", "baiyuliang"+(i+1));
map.put("mood", "今天心情不错哈!!!");
map.put("creatdate", new SimpleDateFormat("HH:mm:ss").format(new Date()));
listItem.add(map);
}
mAdapter = new MyAdapter(this, listItem);
mRefreshListView.setAdapter(mAdapter);
mRefreshListView.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onRefresh() {
// 异步查询数据
new AsyncTask<Void, Void, Void>(){
@Override
protected Void doInBackground(Void... params) {
SystemClock.sleep(1000);
map=new HashMap<String, String>();
map.put("username", "new");
map.put("mood", "我是被下拉刷新出来的");
map.put("creatdate", new SimpleDateFormat("HH:mm:ss").format(new Date()));
listItem.add(0,map);
return null;
}
protected void onPostExecute(Void result) {
mAdapter.notifyDataSetChanged();
// 隐藏头布局
mRefreshListView.onRefreshFinish();
}
}.execute(new Void[]{});
}
@Override
public void onLoadMoring() {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
SystemClock.sleep(2000);
for (int i = 0; i < 10; i++) {
map=new HashMap<String, String>();
map.put("username", "baiyuliang");
map.put("mood", "上拉刷新出来的数据"+(i+1));
map.put("creatdate", new SimpleDateFormat("HH:mm:ss").format(new Date()));
listItem.add(map);
}
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
mAdapter.notifyDataSetChanged();
mRefreshListView.onRefreshFinish();
}
}.execute(new Void[]{});
}
});
}
}
这个跟普通的listView适配一样,我想大家都知道该怎么做,主要就是我们重写的RefreshListView中包含了两个监听,下拉刷新和上拉加载需要在这里实现,对listview的更新我们需用到notifyDataSetChanged()方法,这个也不需要我多说,我想大家都应该知道,最后我们看一下,头部布局:
<?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:orientation="horizontal" >
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal"
android:padding="5dp">
<ImageView
android:id="@+id/iv_listview_header_down_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/common_listview_headview_red_arrow" />
<ImageView
android:id="@+id/pb_listview_header_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/refresh_loading"
android:visibility="gone" />
</FrameLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="5dp">
<TextView
android:id="@+id/tv_listview_header_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下拉刷新"
android:textColor="@android:color/darker_gray"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_listview_header_last_update_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dip"
android:text="最后刷新时间: 1990-09-09 09:00:00"
android:textColor="@android:color/darker_gray"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
和脚部布局:
<?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:background="#FFFFFF"
android:orientation="vertical" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="10dp" >
<ImageView
android:id="@+id/pb_listview_footer_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/refresh_loading"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:text="加载更多..."
android:textColor="@android:color/darker_gray"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
其实就这么多,是不是很简单,主要就是我们重写的ListView控件,如果看不明白,大家可以在下面下载我的源码研究:
http://download.csdn.net/detail/baiyuliang2013/7000317
ListView下拉刷新上拉加载更多实现的更多相关文章
- Android 自定义 ListView 上下拉动“刷新最新”和“加载更多”歌曲列表
本文内容 环境 测试数据 项目结构 演示 参考资料 本文演示,上拉刷新最新的歌曲列表,和下拉加载更多的歌曲列表.所谓"刷新最新"和"加载更多"是指日期.演示代码 ...
- SwipeRefreshLayout实现下拉刷新上滑加载
1. 效果图 2.RefreshLayout.java package myapplication.com.myapplication; import android.content.Context; ...
- Android 下拉刷新上啦加载SmartRefreshLayout + RecyclerView
在弄android刷新的时候,可算是耗费了一番功夫,最后发觉有现成的控件,并且非常好用,这里记录一下. 原文是 https://blog.csdn.net/huangxin112/article/de ...
- juery下拉刷新,div加载更多元素并添加点击事件(二)
buffer.append("<div class='col-xs-3 "+companyId+"' style='padding-left: 10px; padd ...
- 移动端下拉刷新上拉加载-mescroll.js插件
最近无意间看到有这么一个上拉刷新下拉加载的插件 -- mescroll.js,个人感觉挺好用的,官网地址是:http://www.mescroll.com 然后我就看了一下文档,简单的写了一个小dem ...
- Android如何定制一个下拉刷新,上滑加载更多的容器
前言 下拉刷新和上滑加载更多,是一种比较常用的列表数据交互方式. android提供了原生的下拉刷新容器 SwipeRefreshLayout,可惜样式不能定制. 于是打算自己实现一个专用的.但是下拉 ...
- ListView实现Item上下拖动交换位置 并且实现下拉刷新 上拉加载更多
ListView实现Item上下拖动交换位置 并且实现下拉刷新 上拉加载更多 package com.example.ListViewDragItem; import android.app.Ac ...
- listview下拉刷新上拉加载扩展(三)-仿最新版美团外卖
本篇是基于上篇listview下拉刷新上拉加载扩展(二)-仿美团外卖改造而来,主要调整了headview的布局,并加了两个背景动画,看似高大上,其实很简单: as源码地址:http://downloa ...
- listview下拉刷新上拉加载扩展(二)-仿美团外卖
经过前几篇的listview下拉刷新上拉加载讲解,相信你对其实现机制有了一个深刻的认识了吧,那么这篇文章我们来实现一个高级的listview下拉刷新上拉加载-仿新版美团外卖的袋鼠动画: 项目结构: 是 ...
随机推荐
- 关于myeclipse启动报错:An internal error has occurred. java.lang.NullPointerException解决办法
启动myeclipse报错,百度了一下网友处理方式,对比日志,发现现在已有的教程真的是巨人坑: 如果出现了上述的错误按照如下的3个步骤解决:1.首先关闭MyEclipse工作空间.2.然后删除工作空间 ...
- Hibernate注解开发详解
*****************关于注解的简单介绍 详细介绍请点击这里注解详细教程 package com.tomowork.pojo; import org.hibernate.annotatio ...
- python 网络爬虫(一)爬取天涯论坛评论
我是一个大二的学生,也是刚接触python,接触了爬虫感觉爬虫很有趣就爬了爬天涯论坛,中途碰到了很多问题,就想把这些问题分享出来, 都是些简单的问题,希望大佬们以宽容的眼光来看一个小菜鸟
- HDU 2082 找单词
Problem Description 假 设有x1个字母A, x2个字母B,..... x26个字母Z,同时假设字母A的价值为1,字母B的价值为2,..... 字母Z的价值为26.那么,对于给定的字 ...
- [USACO12FEB]牛的IDCow IDs
题目描述 Being a secret computer geek, Farmer John labels all of his cows with binary numbers. However, ...
- 计蒜客NOIP模拟赛4 D1T2小X的密室
小 X 正困在一个密室里,他希望尽快逃出密室. 密室中有 N 个房间,初始时,小 X 在 1 号房间,而出口在 N 号房间. 密室的每一个房间中可能有着一些钥匙和一些传送门,一个传送门会单向地创造一条 ...
- 搭积木(block)
[问题描述]小 OY 是一个喜欢搭积木的孩子,他有一天决定向小 C 展示他特别的搭积木技巧.现在一条直线上从左到右有 n 个位置,标号 1..n,第 i 个位置坐标为 x_i.每个位置上都预先叠好了一 ...
- hdu 5885 FFT
XM Reserves Time Limit: 10000/10000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others)T ...
- 2015 多校联赛 ——HDU5414()
Problem Description CRB has two strings s and t. In each step, CRB can select arbitrary character c ...
- 51Nod 1530 稳定方块
瓦西亚和皮台亚摆放了m个方块.方块被编号为0到m-1(每个号码出现恰好一次).现在建立一个座标系OX表示地面,OY的方向是竖直向上的.每一方块的左下角有一个座标而且是整点座标. 摆放好的方块一定要是稳 ...