滑动更改ListView的标题

转载请注明出处:  http://blog.csdn.net/forwardyzk/article/details/42710837

我们平时看到当滑动ListView时,标题的内容会不断的更改,并且标题会有一个推动的效果,下面与大家共享一个示例。

思路:

1.自定义ListView,给ListView绘画一个子标题(childView),将其位置设置为(0,0,width,height)

2.给ListView添加滑动监听事件。

当向下滑动时,当前第一个完全显示的item的标题内容和标题内容进行比较

如果一样,则不更改标题内容和位置,

如果不一样,则把标题的内容更改为当前显示的第一个item的标题内容,并且更改标题位置

当向上滑动时,当前第一个显示item的标题内容和标题内容进行比较

如果一样,则不更改标题内容和位置,

如果不一样,则把标题标题的内容更改为当前显示的第一个item的标题内容,并且更改标题位置

自定义一个PinnedHeaderListView集成ListView

public class PinnedHeaderListView extends ListView {

	/**
	 * 更改标题的接口
	 *
	 */
	public interface PinnedHeaderConfig {
		void configurePinnedHeader(View header, int position);
	}

	private PinnedHeaderConfig mAdapter;
	private View mHeaderView;
	private boolean mHeaderViewVisible;
	private int mHeaderViewWidth;
	private int mHeaderViewHeight;

	public PinnedHeaderListView(Context context) {
		super(context);
	}

	public PinnedHeaderListView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

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

	public void setPinnedHeaderView(View view) {
		mHeaderView = view;
		if (mHeaderView != null) {
			setFadingEdgeLength(0);
		}
		showLog("setPinnedHeaderView");
	}

	@Override
	public void setAdapter(ListAdapter adapter) {
		super.setAdapter(adapter);
		mAdapter = (PinnedHeaderConfig) adapter;
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		// 测量长和宽
		if (mHeaderView != null) {
			showLog("onMeasure");
			measureChild(mHeaderView, widthMeasureSpec, heightMeasureSpec);
			mHeaderViewWidth = mHeaderView.getMeasuredWidth();
			mHeaderViewHeight = mHeaderView.getMeasuredHeight();
		}
	}

	@Override
	protected void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		super.onLayout(changed, left, top, right, bottom);
		if (mHeaderView != null) {
			showLog("onLayout");
			mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);
			moveTitle(getFirstVisiblePosition());
		}
	}

	/**
	 * 处理标题的移动
	 *
	 * @param position
	 */
	public void moveTitle(int position) {
		if (mHeaderView == null) {
			return;
		}
		View firstView = getChildAt(0);
		int bottom = firstView.getBottom();
		int headerHeight = mHeaderView.getHeight();
		int y;
		if (bottom < headerHeight) {
			y = (bottom - headerHeight);
		} else {
			y = 0;
		}
		// 设置标题显示的内容
		mAdapter.configurePinnedHeader(mHeaderView, position);
		if (mHeaderView.getTop() != y) {
			mHeaderView.layout(0, y, mHeaderViewWidth, mHeaderViewHeight + y);
		}
		mHeaderViewVisible = true;
	}

	@Override
	protected void dispatchDraw(Canvas canvas) {
		super.dispatchDraw(canvas);
		if (mHeaderViewVisible) {
			showLog("dispatchDraw");
			drawChild(canvas, mHeaderView, getDrawingTime());
		}
	}

	public void showLog(String message) {
		Log.d("MESSAGE", message);
	}
}

setPinnedHeaderView(View view):给ListView添加一个标题。

在onMeasure()中先测量一个此标题的长和宽,

measureChild(mHeaderView, widthMeasureSpec, heightMeasureSpec);表示先访问Listview其中的一个标题,容纳后获取其长和宽。

在onLayout()中制定显示的位置,mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);其中长和宽是在onMeasure()中获取的。

然后在dispatchDraw(Canvas canvas)把其标题View绘画出来,此方法主要是绘画子组件,使用drawChild()方法进行绘制。

/**
 * Item信息Bean类
 *
 */
public class ItemInfo {

	private String title;// 标题
	private String content;// 内容

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

}

在ListView的滑动监听事件中,控制标题的移动和内容的变换

@Override
	public void onScroll(AbsListView view, int firstVisibleItem,
			int visibleItemCount, int totalItemCount) {
		if (view instanceof PinnedHeaderListView) {
			showLog("adapter-onScroll");
			// 处理的是向下滑动
			if (!data
					.get(firstVisibleItem + 1 < data.size() ? firstVisibleItem + 1
							: data.size() - 1).getTitle().equals(titleContent)) {
				((PinnedHeaderListView) view).moveTitle(firstVisibleItem);
			} else {
				// 处理向上滑动
				if (!data.get(firstVisibleItem).getTitle().equals(titleContent)) {
					((PinnedHeaderListView) view).moveTitle(firstVisibleItem);
				}
			}
		}
	}

我们要处理的是向上滑动和向下滑动两种情况,不管是向上滑动还是向下滑动,适当的时候都需要更改标题的内容和位置,在这里判断的依据,当前显示的第一个item的标题和其下一个item的标题的内容不一样的时候,需要进行标题更改标题的内容,当前显示的第一个标题的item完全不显示时,其标题内容发生了变化(更改为此时第一个Item的标题内容)。

标题的移动

public void moveTitle(int position) {
		if (mHeaderView == null) {
			return;
		}
		View firstView = getChildAt(0);
		int bottom = firstView.getBottom();
		int headerHeight = mHeaderView.getHeight();
		int y;
		if (bottom < headerHeight) {
			y = (bottom - headerHeight);
		} else {
			y = 0;
		}
		// 设置标题显示的内容
		mAdapter.configurePinnedHeader(mHeaderView, position);
		if (mHeaderView.getTop() != y) {
			mHeaderView.layout(0, y, mHeaderViewWidth, mHeaderViewHeight + y);
		}
		mHeaderViewVisible = true;
	}

Y方向位置发生的变化值(ListView第一个Item的底部和标题View的高度差值)

mHeaderView.layout(0, y, mHeaderViewWidth, mHeaderViewHeight + y);

mAdapter.configurePinnedHeader(mHeaderView, position);设置标题的内容

public void configurePinnedHeader(View header, int position) {
		showLog("adapter-configurePinnedHeader");
		titleContent = data.get(position).getTitle();
		((TextView) header.findViewById(R.id.header_text)).setText(String
				.valueOf(titleContent));
	}

使用步骤:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/listView"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <com.example.view.PinnedHeaderListView
        android:id="@+id/section_list_view"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="@null" />

</LinearLayout>

MainActivity.java

public void initView() {
		List<ItemInfo> list = new ArrayList<ItemInfo>();
		ItemInfo info;
		for (int i = 0; i < 50; i++) {
			info = new ItemInfo();
			info.setTitle(String.valueOf(i / 5) + "组");
			info.setContent("这是第 " + i + " Item");
			list.add(info);
		}
		adapter = new ListViewAdapter(getLayoutInflater());
		adapter.setData(list);
		listView = (PinnedHeaderListView) findViewById(R.id.section_list_view);
		listView.setAdapter(adapter);
		listView.setOnScrollListener(adapter);
		listView.setPinnedHeaderView(getLayoutInflater().inflate(
				R.layout.child_titleview_section, listView,
				false));

	}

setPinnedHeaderView():设置标题View,和在适配器中更改标题中的TextView的id就是其View中的控件

setData()设置加载的数据,ItemInfo

setOnScrollListener()设置滚动监听,这里适配器实现额OnScrollListener接口,所以可以直接写适配器对象

源码下载:
http://download.csdn.net/detail/forwardyzk/8361563

效果图:

时间: 2024-11-10 17:50:47

滑动更改ListView的标题的相关文章

通过重写ScrollView和Listview完成上下滑动选中不同位置标题的效果

  点击这里源码下载 看到了吗?就是这种效果:我再跟大家简单的叙述一下: 头部标题有三个:剧本梗概.剧本正文.剧本介绍. 当ScrollView滑到剧本中的无论哪一个内容标题的时候头部的大标题将被选中并呈现橙色:而三个标题内容下面是ListView的item,嵌在其父控件Scrollview中的. 下面让我们分析一下代码: 布局:activity_main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/r

横向滑动的listview效果的实现方法,scrollview嵌套水平滑动的listview卡顿的解决方法

很多时候,界面需要实现横向滑动的listview效果.网络上有一种方法,自定义了HorizontalListView,用法同正常的listview,可实现水平滑动效果. 但是如果一个界面 为垂直滑动的scrollview嵌套水平滑动的listview的时候,滑动水平listview的时候,会很卡.我最近就遇到了这样的问题,一直把思路放在监听水平和垂直滑动手势,想实现滑动角度小于45的时候 垂直的scrollview 滑动效果被禁止.但是一直没有研究出来. 于是一个偶然的机会,灵光一闪,想到用Ho

滑动删除ListView的Item的效果

本例子实现了滑动删除ListView的Itemdemo的效果.大家都知道.这种创意是来源于IOS的.左滑删除的功能.在Android上面实现比较麻烦.本例子中不仅实现了左滑删除功能.还实现了左滑赞.左滑分享.左滑收藏等功能.当然大家也可以根据自己项目的需求来修改功能.QQ和微信也实现了相同的功能.大家可以看看.先上程序运行的效果 采用的恶事一个开源库swipemenulistview.jar 代码如下 布局 <com.baoyz.swipemenulistview.SwipeMenuListVi

【Android - 问题解决】之ScrollView嵌套ListView时总是自动滑动到ListView顶部的问题

最近做了一个项目,里面有一个ScrollView嵌套ListView的布局. 做出来之后发现,进入这个界面之后,总是自动滑动到ListView的顶部,而ScrollView中位于ListView上面的一些控件就被挤到屏幕外面去了. 解决这个问题的方法如下: 在JAVA代码中,调用ScrollView对象的这个方法: scrollView.smoothScrollTo(0, 0);

Android HorizontalScrollView 水平滑动 在listview上面动态添加图片

Android HorizontalScrollView   水平滑动    listview 上动态添加图片 最近遇到了个 在listview展示广告的需要动态添加图片 如图: 使用了 horizontalScrollView   在listview上进行添加 java代码: package com.baozi.bzhorizontalscrollview; import java.util.ArrayList; import android.app.Activity; import andr

word中更改图片和标题之间的垂直距离

word中插入图片后,往往需要给图片加上标题. 你插入图片和给图片插入标题时,word用的是默认的格式给你插入的图片和标题. 假如原来的paragraph是2倍行距,你的图片和标题之间的距离也是2倍行距,这样显的你的图片和标题之间的距离特别大. 插入完成后,你想调节图片和标题的距离,就不可能了.因为行距是前一行和后一行直接的距离,但是图片并没有行距. 解决方法如下: 1.删除你的图片和图片标题. 2. 在你插入图片的上一行之下插入两个回车 3. 选中你插入的回车,邮件点击"段落",把行

滑动页面带个标题。。。

跟滑动页面一样的效果不过带个标题. 与滑动页面一样的步骤先配置六个页面 然后新建main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:l

Android自定义view 滑动开关 支持左右滑动 适用于listview

要做这样一种开关. 当开关在左边时,都是灰色的,向右滑动的时候,滑到一半的时候,改变颜色,变成绿色: 当开关在右边是,都市绿色的,向左滑动的时候,滑动一半的时候,改变颜色,变成灰色. 这里就要涉及要可滑动最大距离,以及你现在滑动的距离.通过这个来比较,改变颜色. import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.

滑动删除ListView的Item

转载请注明出处: http://blog.csdn.net/forwardyzk/article/details/42643865 在玩QQ的时候,我们会看到这样的效果,可以滑动删除消息,下面就模拟一下这样的效果. 1.创建一个类ListViewCompat,继承ListView. 重写其OnTouchEvent事件. @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { c