转自博客园 农民伯伯
http://www.cnblogs.com/over140/archive/2011/12/07/2275207.html
前言
ListView是一个纵向滚动的列表视图,也有朋友嵌套HorizontalScrollView来实现,比如这里,但在ListView的API中明确指明了两者不可同时使用,参考ListView的中文API这里。本文分享一种办法,以方便有此需求的朋友。
博客园:http://www.cnblogs.com
农民伯伯: http://over140.cnblogs.com
Android中文翻译组:http://androidbox.sinaapp.com/
a). 支持ListView横行滚动
b). 支持固定第一列
package cn.com.test;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class ScrollListView extends RelativeLayout {
private Context mContext;
/**
* 列表头的高和宽
*/
private int mTitleHeight = 30;
private int mTitleWidth = 60;
/**
* 可滚动和不可滚动列头的名称
*/
private String[] mTitleMovableStr = { "测试1", "测试2", "测试3", "测试4", "测试5",
"测试6", "测试7", "测试8", "测试9" };
private String[] mTitleFixStr = { "测试10", "测试11" };
private LinearLayout mLayoutTitleMovable;
private LinearLayout mLayoutHeader;
private LinearLayout mLayoutListMovable;
private ListView listViewMovable;
private ArrayList<View> mArrayList;
public ScrollListView(Context context) {
super(context);
mContext = context;
}
public ScrollListView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
// ListView可移动区域
mLayoutListMovable = new LinearLayout(mContext);
mLayoutListMovable.setOrientation(LinearLayout.VERTICAL);
LayoutParams scrollListLp = new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT);
this.addView(buidScrollListView(), scrollListLp);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 可滚动得列表头
*
* @return
*/
private View buildMovableHead() {
LinearLayout relativeLayout = new LinearLayout(mContext);
for (int i = 0; i < mTitleMovableStr.length; i++) {
TextView tx = new TextView(mContext);
tx.setText(mTitleMovableStr[i]);
tx.setGravity(Gravity.CENTER);
tx.setBackgroundColor(Color.GREEN);
relativeLayout.addView(tx, mTitleWidth, mTitleHeight);
}
mLayoutTitleMovable = relativeLayout;
return relativeLayout;
}
/**
* 不可滚动得列表头
*
* @return
*/
private View buildFixHead() {
LinearLayout relativeLayout = new LinearLayout(mContext);
for (int i = 0; i < mTitleFixStr.length; i++) {
TextView tx = new TextView(mContext);
tx.setText(mTitleFixStr[i]);
tx.setGravity(Gravity.CENTER);
tx.setBackgroundColor(Color.RED);
relativeLayout.addView(tx, i, new LayoutParams(mTitleWidth,
mTitleHeight));
}
return relativeLayout;
}
/**
* 合并列头
*
* @return
*/
private View buildHeadLayout() {
LinearLayout relativeLayout = new LinearLayout(mContext);
relativeLayout.addView(buildFixHead());
relativeLayout.addView(buildMovableHead());
mLayoutHeader = relativeLayout;
return relativeLayout;
}
/**
* ListView
*
* @return
*/
private View buildMoveableListView() {
LinearLayout relativeLayout = new LinearLayout(mContext);
listViewMovable = new ListView(mContext);
listViewMovable.setCacheColorHint(00000000);
relativeLayout.addView(listViewMovable);
return relativeLayout;
}
private View buidScrollListView() {
LinearLayout relativeLayout = new LinearLayout(mContext);
relativeLayout.setOrientation(LinearLayout.VERTICAL);
relativeLayout.addView(buildHeadLayout());
relativeLayout.addView(buildMoveableListView());
return relativeLayout;
}
// 触摸开始时X的位置
private float mStartX = 0;
private float mStartY = 0;
// X轴方向的偏移量
private int mOffsetX = 0;
private int fixX = 0;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mStartX = ev.getX();
mStartY = ev.getY();
Log.e("TEST", "中断按下x= " + ev.getX());
break;
case MotionEvent.ACTION_MOVE:
Log.e("TEST", "中断移动x= " + ev.getX());
int offsetX = (int) Math.abs(ev.getX() - mStartX);
if (offsetX > 30) {
return true;
} else {
return false;
}
case MotionEvent.ACTION_UP:
Log.e("TEST", "中断抬起x= " + ev.getX());
actionUP();
break;
default:
break;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e("TEST", "移动按下x= " + ev.getX());
return true;
case MotionEvent.ACTION_MOVE:
int offsetX = (int) Math.abs(ev.getX() - mStartX);
if (offsetX > 30) {
Log.e("TEST", "移动偏移" + offsetX);
mOffsetX = (int) (mStartX - ev.getX());
mLayoutTitleMovable.scrollTo(mOffsetX, 0);
for (int i = 0; i < mArrayList.size(); i++) {
mArrayList.get(i).scrollTo(mOffsetX, 0);
}
Log.e("TEST", "List数量" + mArrayList.size());
// mLayoutMovable.scrollTo(mOffsetX, 0);
}
break;
case MotionEvent.ACTION_UP:
Log.e("TEST", "移动抬起x= " + ev.getX());
fixX = (int) ((int) ev.getX() - mStartX);
actionUP();
break;
default:
break;
}
return super.onTouchEvent(ev);
}
/**
* 触摸抬起
*/
private void actionUP() {
if (fixX > 0) {
mLayoutTitleMovable.scrollTo(0, 0);
for (int i = 0; i < mArrayList.size(); i++) {
mArrayList.get(i).scrollTo(0, 0);
}
// mLayoutMovable.scrollTo(0, 0);
} else {
if ((mLayoutTitleMovable.getWidth() + Math.abs(fixX)) > mTitleWidth
* mTitleMovableStr.length) {
mLayoutTitleMovable.scrollTo(mTitleWidth
* mTitleMovableStr.length-mLayoutTitleMovable.getWidth(), 0);
for (int i = 0; i < mArrayList.size(); i++) {
mArrayList.get(i).scrollTo(mTitleWidth
* mTitleMovableStr.length-mLayoutTitleMovable.getWidth(), 0);
}
// mLayoutMovable.scrollTo(0, 0);
}
}
}
/**
* 设置可变的列表头信息
*
* @param str
* 列表头显示的名称
*/
public void setMovableHead(String[] str) {
mTitleMovableStr = str;
}
/**
* 设置不可变的列表头信息
*
* @param str
* 列表头显示的名称
* @param height
* 列表头的高度
* @param width
* 列表头的宽度
*/
public void setFixHead(String[] str, int height, int width) {
mTitleHeight = height;
mTitleWidth = width;
mTitleFixStr = str;
}
public View getHeaderLayout(){
return mLayoutHeader;
}
/**
* 设置ListView 适配器
*
* @param adapter
*/
public void setScrollListViewAdapter(
BaseAdapter movableAdapter) {
// listViewFix.setAdapter(fixAdapter);
listViewMovable.setAdapter(movableAdapter);
}
/**
* 可左右滑动View集合
* @param movableView
*/
public void setMovabaleView(ArrayList<View> movableView) {
mArrayList = movableView;
}
/**
* listView 点击
* @param onItemClickedListener
*/
public void setOnItemClickedListener(
OnItemClickListener onItemClickListener) {
listViewMovable.setOnItemClickListener(onItemClickListener);
}
/**
* 列头点击事件
* @param onHeaderClickedListener
*/
public void setOnHeaderClickedListener(
OnHeaderClickedListener onHeaderClickedListener) {
// onHeaderClickedListener.
// mLayoutHeader.getChildAt(0).setOnClickListener(l);
}
/**
* 列头点击事件
*
* @createTime 2011-9-26
* @company 深圳市创真科技
* @author niuxuehao
*/
public static interface OnHeaderClickedListener {
public void onClick(int headerID, int direction);
}
}
- 大小: 323 KB
分享到:
相关推荐
这里我们将深入探讨如何在Android中实现"ListView固定表头,固定前几列"的功能。 首先,我们来看表头的固定。表头固定通常是通过自定义ViewGroup来实现的。创建一个新的布局文件,比如`fixed_header.xml`,作为表头...
标题"Android ListView 固定列头源码"提示我们将讨论如何在ListView中实现这样的功能。 在Android中,实现ListView固定列头的一种常见方法是使用自定义适配器和布局管理器。一种常见的实现方式是创建两个ListView:...
"android listview 固定列头"正是这样一个技术点,它允许开发者在ListView中创建一个可左右拖动的、自定义的列头。 要实现这个功能,我们需要理解以下几个关键知识点: 1. **自定义ViewGroup**: 首先,我们需要...
在特定场景下,我们可能需要实现ListView的头部固定以及某列固定的效果,同时允许用户进行上下左右滑动来浏览更多的内容。这个功能在设计用户界面时,能够提供更好的用户体验,尤其是在处理大数据表格或者长列表时。...
总之,实现"ListView表头和第一列固定不动上下左右滑动"的功能需要对Android布局管理、滚动事件处理以及性能优化有深入理解。通过自定义组件、使用第三方库或者结合现有组件,都可以达到预期效果。在实际开发中,应...
总之,实现ListView带表头(表头固定)是Android开发中的一个常见需求,它需要理解ListView的工作原理,以及如何在适配器和滚动事件中正确处理表头。通过实践和优化,你可以创建出既美观又高效的列表界面。
总的来说,实现“头部固定不动的listview”涉及到了Android视图复用、滚动事件处理、自定义布局和动画等多个技术点。开发者可以通过`PinnedHeaderExpandableListView`这样的开源库,简化这一复杂功能的实现,同时也...
在“android listview 股东列头”的场景中,我们可能需要实现一个ListView,其中包含股东信息,并且列头是固定的,即使在用户滚动列表时也不会消失。这通常是为了提供更好的用户界面,使用户始终能够看到列头,了解...
- 如果需要有固定表头,可以在ListView的顶部添加一个独立的布局,或者创建一个特殊的表头视图类型。 7. **自定义样式** - 可以通过修改单元格的背景颜色、文字颜色、边框等属性,实现个性化样式。 8. **刷新和...
在Android开发中,有时我们需要创建一个既可横向滚动又可竖向滚动的表格,这通常涉及到自定义ListView和HorizontalScrollView的组合使用。以下是对这个特殊需求的详细解释和实现思路: 首先,我们用ListView来处理...
在Android开发中,ListView是一种非常常用的控件,用于展示大量数据列表。然而,有时我们不仅需要展示单一列表,还可能需要实现类似表格的布局,即行与列的结构。本篇将详细介绍如何在Android中利用ListView实现表格...
在Android开发中,为了提供更好的用户体验,有时我们需要对列表视图(ListView)进行特定的定制,比如锁定指定列。这通常在数据展示时,需要保持某些关键信息始终可见的情况下非常有用。本文将深入探讨如何在Android中...
标题所提到的"Android程序开发之ListView实现横向滚动(带表头与固定列)"是针对这种需求的一个解决方案,即在ListView中实现横向滚动,同时保持左侧列(通常是表头)固定,顶部表头在向下滚动时也始终保持可见。...
在Android开发中,ListView是一种非常常见的控件,用于展示大量数据列表。然而,有时我们不仅需要展示单一列表,还可能需要实现类似表格的效果,比如显示多列数据。本篇文章将详细讲解如何在Android中利用ListView...
瀑布流布局的特点是每一列的高度不固定,根据内容自适应,使得视觉效果更加生动,用户体验更佳。在本案例中,我们讨论的是如何在Android中实现瀑布流ListView,并且它已经集成了上拉刷新和下拉分页功能,以提供更...
在Android开发中,ListView是一种非常常见且重要的组件,它用于展示大量的数据列表,通常用于创建类似于表格的效果。这篇博客“Android Listview表格”探讨了如何在Android应用中使用ListView来构建表格样式的视图。...
1. **理解ListView**: ListView是Android中的一个视图组件,它能够显示一列可滚动的数据项。通常,ListView会与Adapter配合使用,Adapter负责填充数据并决定每个列表项的外观。 2. **Adapter的使用**: Adapter是...
android的ListView上拉刷新下拉加载和列表头横向滚动(带表头与固定列)。 该demo是我结合网上的两个示例一个是上下拉刷新加载的ListView,一个是横向滚动带固定列和列表头.主要是自定义了两个控件(重写)ListView和...
在Android开发中,创建一个类似股票应用的界面是一项常见的任务,尤其当涉及到固定左边列并且支持上下左右滑动的功能时。这个"android 仿股票 固定左边列可上下左右滑动"的项目,旨在实现一种高效且用户体验良好的...
总之,实现固定列的ListView需要对Android的UI组件有深入理解,包括Adapter机制、布局管理以及事件处理。通过自定义Adapter和合理利用布局资源,我们可以创建出满足需求的固定列ListView。在实际开发中,还应考虑...