本文将介绍android–如何将listView标头添加为自定义布局的详细情况,特别是关于listview设置标题的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也
本文将介绍android – 如何将listView标头添加为自定义布局的详细情况,特别是关于listview设置标题的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于Android ExpandableListView具有自定义项目的复杂布局、Android ListView 疯狂之旅 之 《自定义下拉刷新功能的 ListView》、Android ListView 疯狂之旅 之 《自定义下拉刷新功能的ListView》、android listview 自定义的好处的知识。
本文目录一览:- android – 如何将listView标头添加为自定义布局(listview设置标题)
- Android ExpandableListView具有自定义项目的复杂布局
- Android ListView 疯狂之旅 之 《自定义下拉刷新功能的 ListView》
- Android ListView 疯狂之旅 之 《自定义下拉刷新功能的ListView》
- android listview 自定义的好处
android – 如何将listView标头添加为自定义布局(listview设置标题)
我想在listView中添加标题我尝试这样我在这里缺少的ids很好.
我在片段中使用它.
ListView lv;
LinearLayout header = (LinearLayout) rootView.findViewById(R.id.header_layout);
lv.addHeaderView(header);
// APP is crashing here?
logcat的
java.lang.classCastException: android.widget.AbsListView$LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams
at android.widget.RelativeLayout$DependencyGraph.findRoots(RelativeLayout.java:1732)
at android.widget.RelativeLayout$DependencyGraph.getSortedViews(RelativeLayout.java:1677)
at android.widget.RelativeLayout.sortChildren(RelativeLayout.java:381)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:389)
at android.view.View.measure(View.java:17547)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
at android.view.View.measure(View.java:17547)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
at android.view.View.measure(View.java:17547)
解决方法:
我们可以向ListView添加标题,如下所示:
LayoutInflater myinflater = getLayoutInflater();
ViewGroup myHeader = (ViewGroup)myinflater.inflate(R.layout.headerlayout, myListView, false);
myListView.addHeaderView(myHeader, null, false);
但是,根据您的错误,您可能已经在xml和java文件中使用了相对布局,您正在使用LinearLayout.
您还必须将ListView初始化为:
lv=(ListView)findViewById(R.id.yourlistview);`
Android ExpandableListView具有自定义项目的复杂布局
我正在开发一个android应用程序,但遇到了要实现的复杂布局层次结构.该应用程序将列出一个咖啡厅的菜单.截至目前,菜单如下所示:
该列表实现为RecyclerView.视图的自定义适配器负责每个元素的操作.触摸一个元素会增加定单价格,并将1加到所有选定元素中.您也可以单击数字以获取代答对话框并更改金额.
您可以想象那里有很多代码.
这是我要实现的理论布局:
我专注于内部ExpandableListView.基本上我想按食物,饮料等对菜单项进行分类.
我的问题是我不知道如何保留项目布局的“复杂性”.我已经设法仅使用项目名称创建了一个简单的ExpandableListView,如下所示:
但是我真的不知道如何使用我为ExpandableListView中的先前布局创建的项目适配器.不幸的是,我不能共享太多代码,但是我并不需要代码片段,而是更多关于如何实现此功能的指导,想法,技巧…这是我的第一个Android应用程序:-)
任何帮助将不胜感激.
非常感谢!
解决方法:
好吧,我找到了解决我问题的方法,但最终并没有那么复杂.我会尝试总结一下,以防有人遇到同样的情况.
首先,您将必须为ExpandableListView创建一个自定义适配器.我以前的RecyclerView确实有一个自定义适配器,它使用了ViewHolder模式,这使我感到困惑.
实际上,This示例对于了解如何实现自定义适配器非常有用.覆盖的重要方法是getChildView.用这种方法可以构造整个子视图.
@Override
public View getChildView(int listPosition, final int expandedListPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final MenuItem item = (MenuItem) getChild(listPosition, expandedListPosition);
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.menu_item, null);
}
// Save final reference to be able to access it in inner classes
final View finalConvertView = convertView;
// Set the item name
TextView itemName = (TextView) convertView.findViewById(R.id.item_menu_name);
itemName.setText(item.getName());
// Set item price
TextView itemPrice = (TextView) convertView.findViewById(R.id.item_menu_price);
itemPrice.setText(item.getFormattedPrice());
这不是完整的代码,但是您可以看到如何在menu_item.xml布局中获取视图并填充它们:-)
在我使用Android data bingind之前,但我不知道如何在没有ViewHolder的情况下使用它.
Android ListView 疯狂之旅 之 《自定义下拉刷新功能的 ListView》
效果图:
一 首先创建一个类,继承 ListView,编写其构造方法
public class RefreshListView extends ListView {
public RefreshListView(Context context) {
this(context, null);
}
public RefreshListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RefreshListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
}
}
二 在 activity 中使用我们的 RefreshListView 控件
向 ListView 中设置数据的过程与我们 android 中提供的 ListView 设置数据的方式一至,这里就不贴出代码块了
此时运行的效果图
可以看到与我们正常的 ListView 是一样的
三 向 RefresListView 中添加我们下拉刷新使用到的头布局
头布局中的显示,包括显示下拉状态的向下的指示箭头,包括指示正在加载中的圆形进度条,包括显示状态与时间的文本框
定义头布局文件
xlistview_footer.xml 文件中
<pre name="code" class="html"><?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="wrap_content"
android:gravity="bottom" >
<RelativeLayout
android:id="@+id/xlistview_header_content"
android:layout_width="fill_parent"
android:layout_height="60dp" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:orientation="vertical"
android:id="@+id/xlistview_header_text">
<TextView
android:id="@+id/xlistview_header_hint_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下拉刷新" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="上次更新时间:"
android:textSize="12sp" />
<TextView
android:id="@+id/xlistview_header_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
<ImageView
android:id="@+id/xlistview_header_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/xlistview_header_text"
android:layout_centerVertical="true"
android:layout_marginLeft="-35dp"
android:src="@drawable/xlistview_arrow" />
<ProgressBar
android:id="@+id/xlistview_header_progressbar"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignLeft="@id/xlistview_header_text"
android:layout_centerVertical="true"
android:layout_marginLeft="-40dp"
android:visibility="visible" />
</RelativeLayout>
</LinearLayout>
将头布局文件添加给 ListView
在 RefresListView 中
private void init(Context context) {
View view = View.inflate(context,R.layout.xlistview_header,null);
this.addHeaderView(view);
}
四 隐藏我们添加的头布局
首先让系统去帮我们测量头布局的高度,测量好后,我们就可以设置头布局的显示位置
private void init(Context context) {
View view = View.inflate(context, R.layout.xlistview_header, null);
view.measure(0, 0);
final int measuredHeight = view.getMeasuredHeight();
view.setPadding(0,-measuredHeight,0,0);
this.addHeaderView(view);
}
五 设置头布局与 LisView 的联动
使用我们的控件实现 OnTouchListener 接口,并复写 onTouch 方法
import android.view.View.OnTouchListener;
public class RefreshListView extends ListView implements OnTouchListener {....
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
}
在 onTouch 方法中我们需要重新设置显示头布局,所以我们需要将部分变量修改为成员变量
private void init(Context context) {
setOnTouchListener(this);
//获取头布局
mHeaderView = View.inflate(context, R.layout.xlistview_header, null);
//进行测量
mHeaderView.measure(0, 0);
//获取头布局的高度
mHeaderHeight = mHeaderView.getMeasuredHeight();
//设置头布局显示
mHeaderView.setPadding(0, -mHeaderHeight, 0, 0);
//添加到ListView中
this.addHeaderView(mHeaderView);
}
在 onTouch 方法中进行设置显示随 ListView 的滑动而显示的头布局
@Override
public boolean onTouchEvent( MotionEvent event) {
int downY = 0;
switch ( event.getAction()) {
case MotionEvent.ACTION_DOWN:
//获取按下时的Y轴的位置
downY = (int)event.getY();
break;
case MotionEvent.ACTION_MOVE:
int moveY = (int)event.getY();
//计算在Y轴方向的滑动偏移量,
int diffY = moveY - downY;
//计算我们的头布局需要移动的距离
int paddingTop = -mHeaderHeight +diffY;
//设置显示头布局
mHeaderView.setPadding(0,paddingTop,0,0);
break;
default:
break;
}
return true;
}
注:这里之所以使用使用的是 - mHeaderHeight 高度,是因为我们在上面设置的头布局的 paddingTop 的大小正好是头布局的高度,也就是说刚刚好将头布局显示在屏幕外侧
优化代码
//设置显示头布局,当显示的条目为第一条的时候并且移动的距离大于0的时候再开时向下移动
if(getFirstVisiblePosition()==0&&diffY>0){
mHeaderView.setPadding(0,paddingTop,0,0);
return true;
}
六 定义更新下拉刷新过程中的头布局显示变化
定义下拉至释放刷新的中的变量
// 代表下拉刷新状态
private final int PULL_REFRESH_STATE = 0;
// 释放刷新状态
private final int RELEASE_STATE = 1;
// 正在刷新状态
private final int RELEASEING = 2;
// 默认当前是下拉刷新状态
private int header_current_state = PULL_REFRESH_STATE;
创建更新头布局的方法
//更新头布局的方法
private void updateHeaderView() {
switch (header_current_state) {
case PULL_REFRESH_STATE: //下拉刷新状态
break;
case RELEASE_STATE: //释放刷新状态
break;
case RELEASEING: //正在刷新的状态
break;
}
}
在 onTouchEvent 方法 中 ACTION_MOVE 事件处理中调用使用我们的更新头布局的方法
case MotionEvent.ACTION_MOVE:
int moveY = (int)event.getY();
//计算在Y轴方向的滑动偏移量,
int diffY = moveY - downY;
//计算我们的头布局需要移动的距离
int paddingTop = -mHeaderHeight +diffY;
//设置显示头布局,当显示的条目为第一条的时候并且移动的距离大于0的时候再开时向下移动
if(getFirstVisiblePosition()==0&&diffY>0){
//判断paddingTop 来更新头布局
if (paddingTop > 0 && header_current_state != RELEASE_STATE) {
// System.out.println("进入释放刷新状态");
header_current_state = RELEASE_STATE;
// 更新头布局状态
updateHeaderView();
} else if (paddingTop < 0
&& header_current_state != PULL_REFRESH_STATE) {
// System.out.println("~~~~下拉刷新状态~~~~");
header_current_state = PULL_REFRESH_STATE;
updateHeaderView();
}
mHeaderView.setPadding(0,paddingTop,0,0);
return true;
}
然后我们在方法 updateHeaderView 这个方法中对应的状态下更新设置显示我们头布局中的信息
//显示下拉上拉正在刷新状态的textview
mXlistviewHeaderHintTextview = (TextView) mHeaderView.findViewById(R.id.xlistview_header_hint_textview);
//头布局中显示时间的控件
mXlistviewHeaderTime = (TextView) mHeaderView.findViewById(R.id.xlistview_header_time);
//头布局中显示的指示箭头
mXlistviewHeaderArrow = (ImageView) mHeaderView.findViewById(R.id.xlistview_header_arrow);
//头布局中显示的加载圆形进度条
mXlistviewHeaderProgressbar = (ProgressBar) mHeaderView.findViewById(R.id.xlistview_header_progressbar);
当头布局出现在屏幕上,但是还没有完全显示在屏幕上的时候,指示箭头应当向下,状太信息应当为下拉刷新
当头布局完全显示在屏幕上的时候,指示箭头指示方向向上,状态为释放刷新
//更新头布局的方法
private void updateHeaderView() {
switch (header_current_state) {
case PULL_REFRESH_STATE: //下拉刷新状态
//[1]更改iv状态
mXlistviewHeaderArrow.startAnimation(downAnimation);
//[2]设置 tv_update 状态
mXlistviewHeaderHintTextview.setText("下拉刷新");
//[3]隐藏头布局
mHeaderView.setPadding(0, -mHeaderHeight, 0, 0);
break;
case RELEASE_STATE: //释放刷新状态
mXlistviewHeaderArrow.startAnimation(upAnimation);
mXlistviewHeaderHintTextview.setText("释放刷新");
break;
case RELEASEING: //正在刷新的状态
//[1]把动画图片隐藏
mXlistviewHeaderArrow.setVisibility(View.INVISIBLE);
mXlistviewHeaderArrow.clearAnimation();
//[2]显示进度条
mXlistviewHeaderProgressbar.setVisibility(View.VISIBLE);
//[3]刷新状态的文字改为 正在刷新
mXlistviewHeaderHintTextview.setText("正在刷新ing");
//[4]设置头布局回到屏幕顶部
mHeaderView.setPadding(0, 0, 0, 0);
break;
}

在 onTouchEvent 中处理 ACTION_UP 事件
如果当前的状态是释放刷新,那当手指抬起的时候,我们将要进行正在刷新状态,并进行相关 UI 显示更新操作
case MotionEvent.ACTION_UP:
if (header_current_state == PULL_REFRESH_STATE) {
updateHeaderView();
}else if (header_current_state == RELEASE_STATE) {
//[1]把正在刷新状态 赋值给 当前状态
header_current_state = RELEASEING;
//[2]调用更新头布局的方法
updateHeaderView();
//[3]更新为下拉状态
// header_current_state =PULL_REFRESH_STATE;
}
break;

可以看到上面使用到了将指示箭头进行旋转操作的动画,可以在构造中进行初始化操作
private RotateAnimation upAnimation;
private RotateAnimation downAnimation;
//初始化头布局 图片旋转的动画
private void initAnim() {
//向上旋转的动画
upAnimation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
upAnimation.setDuration(500);//设置动画执行的时长
upAnimation.setFillAfter(true);
//向下旋转的动画
downAnimation = new RotateAnimation(-180, -360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
downAnimation.setDuration(500);//设置动画执行的时长
downAnimation.setFillAfter(true);
}
七 设置下拉刷新的监听回调接口
//设置下拉刷新数据的接口
public interface OnPullDownRefreshListener{
public void onPullDownRefresh();
}
private OnPullDownRefreshListener mOnPullDownRefreshListener;
//设置刷新的监听
public void setOnPullDownRefreshListener(OnPullDownRefreshListener listener){
mOnPullDownRefreshListener = listener;
}
然后在 onTouchEvent 方法中的 ACTION_UP 事件中片回调
if (mOnPullDownRefreshListener!=null) {
mOnPullDownRefreshListener.onRefresh();
}
八 设置加载数据完成后,隐藏头布局并更新显示时间
ublic void setOnLoadFinish() {
//[0]进度条隐藏
mXlistviewHeaderProgressbar.setVisibility(View.INVISIBLE);
//[2]在这里更新时间
mXlistviewHeaderTime.setText(getCurrentTimerr());
//[3]隐藏头布局
mHeaderView.setPadding(0, -mHeaderHeight, 0, 0);
//[4]把状态置为下拉状态
header_current_state = PULL_REFRESH_STATE;
}
也就是说当我们的数据更新完毕后,需要调用我们设置的方法将显示刷新头布局隐藏,并更新相应的状态与显示信息
更新刷新显示的时间 :
public String getCurrentTimerr(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(new Date());
}
到这里,我们的这个完整的具有下拉刷新功能的 ListView 就可以进行使用了
九 添加上拉加载更多数据功能
private void initFootView() {
//[1]通过打气筒把一个布局转换成一个view对象
mfootView = View.inflate(getContext(), R.layout.xlistview_footer, null);
mfootView.measure(0, 0);
footHeight = mfootView.getMeasuredHeight();
//[1]默认情况隐藏脚布局
mfootView.setPadding(0, -footHeight, 0, 0);
//[2]添加脚布局
this.addFooterView(mfootView);
//[3]给listview设置滑动监听
this.setOnScrollListener(this);
}

脚布局文件中 :
<pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dp" >
<TextView
android:id="@+id/xlistview_footer_hint_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/xlistview_footer_hint_normal" />
<ProgressBar
android:layout_toLeftOf="@id/xlistview_footer_hint_textview"
android:id="@+id/xlistview_footer_progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible" />
</RelativeLayout>
可以看到这里设置了一个滑动监听,在这里我们需要将我们的控件实现滑动监听事件
public class RefreshListView extends ListView implements AbsListView.OnScrollListener {
...
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
}
设置上拉加载更多的回调监听
private OnUpLoadingMoreListener mOnUpLoadingMoreListener;
public void setOnLoadingMoreListener(OnUpLoadingMoreListener l){
mOnUpLoadingMoreListener = l;
}
public interface OnUpLoadingMoreListener{
public void onLoadingMore();
}
在 listView 的滑动监听事件中回调监听方法
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState== SCROLL_STATE_IDLE ||scrollState == SCROLL_STATE_FLING) {
//判断lisview 是否滑动到了底部
if (getLastVisiblePosition()==getCount()-1 ) {
//[1]把脚布局显示出来
mfootView.setPadding(0, 0, 0, 0);
if (mOnUpLoadingMoreListener!=null) {
mOnUpLoadingMoreListener.onLoadingMore();
}
}
}
}
设置加载完成后调用方法来隐藏加载更多的显示布局
//加载更多完成 需要处理的逻辑
public void setOnLoadIngMoreFinish() {
//[1]把加载更多脚布局隐藏
mfootView.setPadding(0, -footHeight, 0, 0);
}
点击下载源码
下载密码:uvfr
Android ListView 疯狂之旅 第一季 《自定义侧拉删除》 | 点击打开链接查看 |
Android ListView 疯狂之旅 第二季 《分组排序显示数据》 | 点击打开链接查看 |
最新脑筋急转: 男人与女人一起比赛猜智力题 ,一般女人会赢,因为” 难得糊涂 “,男的糊涂
本文同步分享在 博客 “早起的年轻人”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与 “OSC 源创计划”,欢迎正在阅读的你也加入,一起分享。
Android ListView 疯狂之旅 之 《自定义下拉刷新功能的ListView》
效果图:
一 首先创建一个类,继承ListView,编写其构造方法public class RefreshListView extends ListView {
public RefreshListView(Context context) {
this(context, null);
}
public RefreshListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RefreshListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
}
}
二 在activity中使用我们的RefreshListView控件
向ListView中设置数据的过程与我们android中提供的ListView设置数据的方式一至,这里就不贴出代码块了
此时运行的效果图
可以看到与我们正常的ListView是一样的
三 向RefresListView中添加我们下拉刷新使用到的头布局头布局中的显示,包括显示下拉状态的向下的指示箭头,包括指示正在加载中的圆形进度条,包括显示状态与时间的文本框
定义头布局文件
xlistview_footer.xml文件中
<pre name="code"><?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="wrap_content"
android:gravity="bottom" >
<RelativeLayout
android:id="@+id/xlistview_header_content"
android:layout_width="fill_parent"
android:layout_height="60dp" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:orientation="vertical"
android:id="@+id/xlistview_header_text">
<TextView
android:id="@+id/xlistview_header_hint_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下拉刷新" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="上次更新时间:"
android:textSize="12sp" />
<TextView
android:id="@+id/xlistview_header_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
<ImageView
android:id="@+id/xlistview_header_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/xlistview_header_text"
android:layout_centerVertical="true"
android:layout_marginLeft="-35dp"
android:src="@drawable/xlistview_arrow" />
<ProgressBar
android:id="@+id/xlistview_header_progressbar"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignLeft="@id/xlistview_header_text"
android:layout_centerVertical="true"
android:layout_marginLeft="-40dp"
android:visibility="visible" />
</RelativeLayout>
</LinearLayout>
将头布局文件添加给ListView
在RefresListView中
private void init(Context context) {
View view = View.inflate(context,R.layout.xlistview_header,null);
this.addHeaderView(view);
}
四 隐藏我们添加的头布局
首先让系统去帮我们测量头布局的高度,测量好后,我们就可以设置头布局的显示位置
private void init(Context context) {
View view = View.inflate(context, R.layout.xlistview_header, null);
view.measure(0, 0);
final int measuredHeight = view.getMeasuredHeight();
view.setPadding(0,-measuredHeight,0,0);
this.addHeaderView(view);
}
五 设置头布局与LisView的联动
使用我们的控件实现OnTouchListener接口,并复写onTouch方法
import android.view.View.OnTouchListener;
public class RefreshListView extends ListView implements OnTouchListener {....
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
}
在onTouch方法中我们需要重新设置显示头布局,所以我们需要将部分变量修改为成员变量
private void init(Context context) {
setonTouchListener(this);
//获取头布局
mHeaderView = View.inflate(context, R.layout.xlistview_header, null);
//进行测量
mHeaderView.measure(0, 0);
//获取头布局的高度
mHeaderHeight = mHeaderView.getMeasuredHeight();
//设置头布局显示
mHeaderView.setPadding(0, -mHeaderHeight, 0, 0);
//添加到ListView中
this.addHeaderView(mHeaderView);
}
在onTouch方法中进行设置显示随ListView的滑动而显示的头布局
@Override
public boolean onTouchEvent( MotionEvent event) {
int downY = 0;
switch ( event.getAction()) {
case MotionEvent.ACTION_DOWN:
//获取按下时的Y轴的位置
downY = (int)event.getY();
break;
case MotionEvent.ACTION_MOVE:
int moveY = (int)event.getY();
//计算在Y轴方向的滑动偏移量,
int diffY = moveY - downY;
//计算我们的头布局需要移动的距离
int paddingTop = -mHeaderHeight +diffY;
//设置显示头布局
mHeaderView.setPadding(0,paddingTop,0,0);
break;
default:
break;
}
return true;
}
注:这里之所以使用使用的是-mHeaderHeight高度,是因为我们在上面设置的头布局的paddingTop的大小正好是头布局的高度,也就是说刚刚好将头布局显示在屏幕外侧
优化代码
//设置显示头布局,当显示的条目为第一条的时候并且移动的距离大于0的时候再开时向下移动
if(getFirstVisiblePosition()==0&&diffY>0){
mHeaderView.setPadding(0,paddingTop,0,0);
return true;
}
六 定义更新下拉刷新过程中的头布局显示变化
定义下拉至释放刷新的中的变量
// 代表下拉刷新状态
private final int PULL_REFRESH_STATE = 0;
// 释放刷新状态
private final int RELEASE_STATE = 1;
// 正在刷新状态
private final int RELEASEING = 2;
// 默认当前是下拉刷新状态
private int header_current_state = PULL_REFRESH_STATE;
创建更新头布局的方法
//更新头布局的方法
private void updateHeaderView() {
switch (header_current_state) {
case PULL_REFRESH_STATE: //下拉刷新状态
break;
case RELEASE_STATE: //释放刷新状态
break;
case RELEASEING: //正在刷新的状态
break;
}
}
在onTouchEvent方法 中ACTION_MOVE事件处理中调用使用我们的更新头布局的方法
case MotionEvent.ACTION_MOVE:
int moveY = (int)event.getY();
//计算在Y轴方向的滑动偏移量,
int diffY = moveY - downY;
//计算我们的头布局需要移动的距离
int paddingTop = -mHeaderHeight +diffY;
//设置显示头布局,当显示的条目为第一条的时候并且移动的距离大于0的时候再开时向下移动
if(getFirstVisiblePosition()==0&&diffY>0){
//判断paddingTop 来更新头布局
if (paddingTop > 0 && header_current_state != RELEASE_STATE) {
// System.out.println("进入释放刷新状态");
header_current_state = RELEASE_STATE;
// 更新头布局状态
updateHeaderView();
} else if (paddingTop < 0
&& header_current_state != PULL_REFRESH_STATE) {
// System.out.println("~~~~下拉刷新状态~~~~");
header_current_state = PULL_REFRESH_STATE;
updateHeaderView();
}
mHeaderView.setPadding(0,paddingTop,0,0);
return true;
}
然后我们在方法updateHeaderView这个方法中对应的状态下更新设置显示我们头布局中的信息
//显示下拉上拉正在刷新状态的textview
mXlistviewHeaderHintTextview = (TextView) mHeaderView.findViewById(R.id.xlistview_header_hint_textview);
//头布局中显示时间的控件
mXlistviewHeaderTime = (TextView) mHeaderView.findViewById(R.id.xlistview_header_time);
//头布局中显示的指示箭头
mXlistviewHeaderArrow = (ImageView) mHeaderView.findViewById(R.id.xlistview_header_arrow);
//头布局中显示的加载圆形进度条
mXlistviewHeaderProgressbar = (ProgressBar) mHeaderView.findViewById(R.id.xlistview_header_progressbar);
当头布局出现在屏幕上,但是还没有完全显示在屏幕上的时候,指示箭头应当向下,状太信息应当为下拉刷新
当头布局完全显示在屏幕上的时候,指示箭头指示方向向上,状态为释放刷新
//更新头布局的方法
private void updateHeaderView() {
switch (header_current_state) {
case PULL_REFRESH_STATE: //下拉刷新状态
//[1]更改iv状态
mXlistviewHeaderArrow.startAnimation(downAnimation);
//[2]设置 tv_update 状态
mXlistviewHeaderHintTextview.setText("下拉刷新");
//[3]隐藏头布局
mHeaderView.setPadding(0, -mHeaderHeight, 0, 0);
break;
case RELEASE_STATE: //释放刷新状态
mXlistviewHeaderArrow.startAnimation(upAnimation);
mXlistviewHeaderHintTextview.setText("释放刷新");
break;
case RELEASEING: //正在刷新的状态
//[1]把动画图片隐藏
mXlistviewHeaderArrow.setVisibility(View.INVISIBLE);
mXlistviewHeaderArrow.clearanimation();
//[2]显示进度条
mXlistviewHeaderProgressbar.setVisibility(View.VISIBLE);
//[3]刷新状态的文字改为 正在刷新
mXlistviewHeaderHintTextview.setText("正在刷新ing");
//[4]设置头布局回到屏幕顶部
mHeaderView.setPadding(0, 0, 0, 0);
break;
}
在onTouchEvent中处理ACTION_UP事件
如果当前的状态是释放刷新,那当手指抬起的时候,我们将要进行正在刷新状态,并进行相关UI显示更新操作
case MotionEvent.ACTION_UP:
if (header_current_state == PULL_REFRESH_STATE) {
updateHeaderView();
}else if (header_current_state == RELEASE_STATE) {
//[1]把正在刷新状态 赋值给 当前状态
header_current_state = RELEASEING;
//[2]调用更新头布局的方法
updateHeaderView();
//[3]更新为下拉状态
// header_current_state =PULL_REFRESH_STATE;
}
break;
可以看到上面使用到了将指示箭头进行旋转操作的动画,可以在构造中进行初始化操作
private RotateAnimation upAnimation;
private RotateAnimation downAnimation;
//初始化头布局 图片旋转的动画
private void initAnim() {
//向上旋转的动画
upAnimation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
upAnimation.setDuration(500);//设置动画执行的时长
upAnimation.setFillAfter(true);
//向下旋转的动画
downAnimation = new RotateAnimation(-180, -360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
downAnimation.setDuration(500);//设置动画执行的时长
downAnimation.setFillAfter(true);
}
七 设置下拉刷新的监听回调接口
//设置下拉刷新数据的接口
public interface OnPullDownRefreshListener{
public void onPullDownRefresh();
}
private OnPullDownRefreshListener mOnPullDownRefreshListener;
//设置刷新的监听
public void setonPullDownRefreshListener(OnPullDownRefreshListener listener){
mOnPullDownRefreshListener = listener;
}
然后在onTouchEvent方法中的ACTION_UP事件中片回调
if (mOnPullDownRefreshListener!=null) {
mOnPullDownRefreshListener.onRefresh();
}
八 设置加载数据完成后,隐藏头布局并更新显示时间
ublic void setonLoadFinish() {
//[0]进度条隐藏
mXlistviewHeaderProgressbar.setVisibility(View.INVISIBLE);
//[2]在这里更新时间
mXlistviewHeaderTime.setText(getCurrentTimerr());
//[3]隐藏头布局
mHeaderView.setPadding(0, -mHeaderHeight, 0, 0);
//[4]把状态置为下拉状态
header_current_state = PULL_REFRESH_STATE;
}
也就是说当我们的数据更新完毕后,需要调用我们设置的方法将显示刷新头布局隐藏,并更新相应的状态与显示信息
更新刷新显示的时间 :
public String getCurrentTimerr(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(new Date());
}
到这里,我们的这个完整的具有下拉刷新功能的ListView就可以进行使用了
九 添加上拉加载更多数据功能private void initFootView() {
//[1]通过打气筒把一个布局转换成一个view对象
mfootView = View.inflate(getContext(), R.layout.xlistview_footer, null);
mfootView.measure(0, 0);
footHeight = mfootView.getMeasuredHeight();
//[1]默认情况隐藏脚布局
mfootView.setPadding(0, -footHeight, 0, 0);
//[2]添加脚布局
this.addFooterView(mfootView);
//[3]给listview设置滑动监听
this.setonScrollListener(this);
}
脚布局文件中 :
<pre name="code"><?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dp" >
<TextView
android:id="@+id/xlistview_footer_hint_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/xlistview_footer_hint_normal" />
<ProgressBar
android:layout_toLeftOf="@id/xlistview_footer_hint_textview"
android:id="@+id/xlistview_footer_progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible" />
</RelativeLayout>
可以看到这里设置了一个滑动监听,在这里我们需要将我们的控件实现滑动监听事件
public class RefreshListView extends ListView implements AbsListView.OnScrollListener {
...
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
}
设置上拉加载更多的回调监听
private OnUpLoadingMoreListener mOnUpLoadingMoreListener;
public void setonLoadingMoreListener(OnUpLoadingMoreListener l){
mOnUpLoadingMoreListener = l;
}
public interface OnUpLoadingMoreListener{
public void onl oadingMore();
}
在listView的滑动监听事件中回调监听方法
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState== SCROLL_STATE_IDLE ||scrollState == SCROLL_STATE_FLING) {
//判断lisview 是否滑动到了底部
if (getLastVisiblePosition()==getCount()-1 ) {
//[1]把脚布局显示出来
mfootView.setPadding(0, 0, 0, 0);
if (mOnUpLoadingMoreListener!=null) {
mOnUpLoadingMoreListener.onLoadingMore();
}
}
}
}
设置加载完成后调用方法来隐藏加载更多的显示布局
//加载更多完成 需要处理的逻辑
public void setonLoadIngMoreFinish() {
//[1]把加载更多脚布局隐藏
mfootView.setPadding(0, -footHeight, 0, 0);
}
点击下载源码
下载密码:uvfr
Android ListView 疯狂之旅 第一季 《自定义侧拉删除》 | 点击打开链接查看 |
Android ListView 疯狂之旅 第二季 《分组排序显示数据》 | 点击打开链接查看 |
最新脑筋急转: 男人与女人一起比赛猜智力题 ,一般女人会赢,因为”难得糊涂“,男的糊涂
android listview 自定义的好处
问下,大家android开发的时候,经常要用的ListView,很多人都是自定义的,请问下自定义的时候,一般是重写哪些方法?要注意什么?什么情况下需要自定义?
今天的关于android – 如何将listView标头添加为自定义布局和listview设置标题的分享已经结束,谢谢您的关注,如果想了解更多关于Android ExpandableListView具有自定义项目的复杂布局、Android ListView 疯狂之旅 之 《自定义下拉刷新功能的 ListView》、Android ListView 疯狂之旅 之 《自定义下拉刷新功能的ListView》、android listview 自定义的好处的相关知识,请在本站进行查询。
本文标签: