转自博客园 农民伯伯
http://www.cnblogs.com/over140/archive/2011/12/07/2275207.html
[img]http://dl.iteye.com/upload/attachment/0070/5507/7496a09d-d864-3cce-95eb-88926385a48f.gif[/img]
前言
ListView是一个纵向滚动的列表视图,也有朋友嵌套HorizontalScrollView来实现,比如这里,但在ListView的API中明确指明了两者不可同时使用,参考ListView的中文API这里。本文分享一种办法,以方便有此需求的朋友。
博客园:http://www.cnblogs.com
农民伯伯: http://over140.cnblogs.com
Android中文翻译组:http://androidbox.sinaapp.com/
a). 支持ListView横行滚动
b). 支持固定第一列
http://www.cnblogs.com/over140/archive/2011/12/07/2275207.html
[img]http://dl.iteye.com/upload/attachment/0070/5507/7496a09d-d864-3cce-95eb-88926385a48f.gif[/img]
前言
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);
}
}