前一段时间写了一个自定义横向滚动条,感觉效果不怎样好( 

Android 自定义横向滚动条

)。又开始改善结构,使用setScrollView写了一个联动进阶版。标题的滚动条和内容数据item数据滚动条都可以联动滚动。竖向是两个listview,但是是使用全局的竖向滚动条来滚动。所以横向与竖向、单击、长按时间都不会受到影响。长按会横向移动到最右端,显示checkbx。先看效果图。

1、实现效果图


2、实现联动效果的,自定义继承自HorizontalScrollView的SyncHorizontalScrollView滚动条

package com.org.scrollview;import android.content.Context;import android.util.AttributeSet;import android.view.View;import android.widget.HorizontalScrollView;/*** @Description:这个类也是从网上找的参考*/public class SyncHorizontalScrollView extends HorizontalScrollView {private View mView;public SyncHorizontalScrollView(Context context) {super(context);// TODO Auto-generated constructor stub}public SyncHorizontalScrollView(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stub} protected void onScrollChanged(int l, int t, int oldl, int oldt) {super.onScrollChanged(l, t, oldl, oldt);//设置控件滚动监听,得到滚动的距离,然后让传进来的view也设置相同的滚动具体if(mView!=null) {mView.scrollTo(l, t);}}/*** 设置跟它联动的view* @param view*/public void setScrollView(View view) {mView = view;}}

3、通用的联动效果的封装类,供需要此效果类继承即可。CustomListScrollManageActivity

package com.org.horizontalscrollview;import java.util.ArrayList;import java.util.LinkedList;import com.org.scrollview.SyncHorizontalScrollView;import android.app.Activity;import android.content.Context;import android.os.Bundle;import android.util.DisplayMetrics;import android.util.Log;import android.view.Gravity;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.BaseAdapter;import android.widget.CheckBox;import android.widget.CompoundButton;import android.widget.LinearLayout;import android.widget.ListAdapter;import android.widget.ListView;import android.widget.ScrollView;import android.widget.TextView;import android.widget.CompoundButton.OnCheckedChangeListener;import android.widget.Toast;public abstract class CustomListScrollManageActivity extends Activity{//列表的标题protected ArrayList mListHeadItemsName = new ArrayList();//每一项checkbox的记录列表protected LinkedList mItemsExtendData;//列表整体标题栏滚动条private SyncHorizontalScrollView mListHScrollView = null;//是否显示第一列protected boolean mIsShowTextIndex = true;//listview的右边适配器protected ListRightAdapter mRightAdapter;//listview的左边适配器protected ListLeftAdapter mLeftAdapter;//处于长按状态true,不是长按状态falseprotected boolean mLongClickStatus = false;//右边的listviewprotected ListView mrightListView;//左边的listviewprotected ListView mleftListView;//整体的根布局protected int mRootLayout = R.layout.layout_common_sroll;//checkbox的状态protected class ItemStatus {public boolean mIsCheckBoxVisible = false;public boolean mIsCheckBoxSelected = false;}//实例化每一项checkbox的记录列表mItemsExtendDataprotected LinkedList GetItemsExtendData() {if (mItemsExtendData == null) mItemsExtendData = new LinkedList();return mItemsExtendData;}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(mRootLayout);}//子类继承后初始化子类数据后,需要调用这个,初始化父类。protected void initView() {mListHScrollView = (SyncHorizontalScrollView) findViewById(R.id.listRightHScrollView);SyncHorizontalScrollView listHeadHScrollView = (SyncHorizontalScrollView) findViewById(R.id.listHeadHScrollView);//设置右边两个横向滚动条的联动滑动mListHScrollView.setScrollView(listHeadHScrollView);listHeadHScrollView.setScrollView(mListHScrollView);mrightListView = (ListView)findViewById(R.id.rightListView);mleftListView = (ListView)findViewById(R.id.leftListView);//设置右边的监听事件mrightListView.setOnItemClickListener(new OnItemClickListener());mrightListView.setOnItemLongClickListener(new OnItemLongClickListener());mListHeadItemsName = getReadListHeadItems();mRightAdapter = new ListRightAdapter(this);mrightListView.setAdapter(mRightAdapter);mLeftAdapter = new ListLeftAdapter(this);mleftListView.setAdapter(mLeftAdapter);recreateHeadControl();initCheckBoxVilible();setCheckBoxStatue(false);refreshListView();}//刷新列表protected void refreshListView(){//禁止了listview的自带的滚动,需要手动计算listview高度,使用滚动条栏滚动SetListViewHeightBasedOnChildren(mleftListView);SetListViewHeightBasedOnChildren(mrightListView);mRightAdapter.notifyDataSetChanged();mLeftAdapter.notifyDataSetChanged();}//加载表头列表数据protected void recreateHeadControl() {TextView headIndex = (TextView)findViewById(R.id.textIndex);setTextParams(headIndex, mListHeadItemsName.size());headIndex.setText("序号");headIndex.setVisibility(mIsShowTextIndex == true?View.VISIBLE:View.GONE);LinearLayout layout_items = (LinearLayout)findViewById(R.id.layoutTextHeadItems);layout_items.removeAllViews();for (int i = 0; i < mListHeadItemsName.size(); i++) {TextView text=new TextView(this);text.setTextColor(getResources().getColor(R.color.list_head));setTextParams(text, mListHeadItemsName.size());text.setText(mListHeadItemsName.get(i));layout_items.addView(text);}}//初始化每一项的CheckBoxprivate void initCheckBoxVilible(){GetItemsExtendData().clear();for (int i = 0; i < getItemsCount(); i++) {ItemStatus itemData = new ItemStatus();// 插入队列GetItemsExtendData().add(itemData);}}//抽象接口,列表标题栏public abstract ArrayList getReadListHeadItems();//抽象接口,listview整体数据项public abstract int getItemsCount();/** * 抽象接口,listview每一项数据的装载,装载返回是 * @param recordIndex * @return  ArrayList */public abstract ArrayList getIndexDataArray(int recordIndex);//////////////////////////////////////////////////////////////需要每一项编辑或者增加,删除数据的抽象接口,请看具体情况自行添加/** * 左边的适配器 * @author Administrator * */public class ListLeftAdapter extends BaseAdapter{private Context mContext;private LayoutInflater mLayoutInflater;public ListLeftAdapter(Context context) {this.mContext = context;mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);}@Overridepublic int getCount() {return getItemsCount();}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn null;}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder viewHolder = null;View view = null;//内部类ViewHolder的作用只是用来查找ID,加载布局。提升效率的if (convertView == null) {viewHolder = new ViewHolder();view = mLayoutInflater.inflate(R.layout.layout_scroll_list_item_left, null);viewHolder.headIndex = (TextView)view.findViewById(R.id.textIndex);view.setTag(viewHolder);}else {view = convertView;viewHolder = (ViewHolder) view.getTag();}//列表标题栏,序号数据装载viewHolder.headIndex.setText(String.valueOf(position));viewHolder.headIndex.setVisibility(mIsShowTextIndex == true ? View.VISIBLE : View.GONE);return view;}}/** * 右边适配器 * @author Administrator * */public class ListRightAdapter extends BaseAdapter implements OnCheckedChangeListener {private Context mContext;private LayoutInflater mLayoutInflater;public ListRightAdapter(Context context) {this.mContext = context;mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);}@Overridepublic int getCount() {Log.e("Show", String.valueOf(getItemsCount()));return getItemsCount();}@Overridepublic Object getItem(int arg0) {return null;}@Overridepublic long getItemId(int arg0) {return arg0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {int nHeadItemCount = mListHeadItemsName.size();ViewHolder viewHolder = null;View view = null;//内部类ViewHolder的作用只是用来查找ID,加载布局。提升效率的if (convertView == null) {viewHolder = new ViewHolder();view = mLayoutInflater.inflate(R.layout.layout_scroll_list_item_right, null);viewHolder.isSelectedCheckBox = (CheckBox) view.findViewById(R.id.checkBoxIsSelected);view.setTag(viewHolder);}else {view = convertView;viewHolder = (ViewHolder) view.getTag();}//合理分配横向滚动layout中textview的大小TextView lisTextView[] = new TextView[nHeadItemCount];LinearLayout layout_items = (LinearLayout)view.findViewById(R.id.layoutTextItems);layout_items.removeAllViews();for (int i = 0; i < nHeadItemCount; i++) {TextView text=new TextView(mContext);text.setGravity(Gravity.CENTER_VERTICAL); setTextParams(text, nHeadItemCount);layout_items.addView(text);lisTextView[i] = text;}//每一项横向滚动数据的装载ArrayList itemsData = getIndexDataArray(position);for(int i=0; i < nHeadItemCount;i++) {String value = itemsData.get(i);lisTextView[i].setText(value);}//多选checkbox的状态if (viewHolder.isSelectedCheckBox != null) {// 设置数据viewHolder.isSelectedCheckBox.setTag(position);viewHolder.isSelectedCheckBox.setVisibility(mItemsExtendData.get(position).mIsCheckBoxVisible == true ? View.VISIBLE: View.INVISIBLE);viewHolder.isSelectedCheckBox.setChecked(mItemsExtendData.get(position).mIsCheckBoxSelected);// 添加事件viewHolder.isSelectedCheckBox.setOnCheckedChangeListener(this);}return view;}@Overridepublic void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {Integer nPosition = (Integer)(buttonView.getTag());mItemsExtendData.get(nPosition.intValue()).mIsCheckBoxSelected = isChecked;}}//listview的内部类private class ViewHolder {TextView headIndex;CheckBox isSelectedCheckBox;}private class OnItemClickListener implements android.widget.AdapterView.OnItemClickListener{@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {CheckBox isSelectedCheckBox = (CheckBox)view.findViewById(R.id.checkBoxIsSelected);if (mLongClickStatus) {//checkbox选择区域增强效果 isSelectedCheckBox.setChecked(!isSelectedCheckBox.isChecked()); return;}Integer nPosition = (Integer)(isSelectedCheckBox.getTag());Toast.makeText(getApplicationContext(), String.valueOf(nPosition), Toast.LENGTH_SHORT).show();}}private class OnItemLongClickListener implements android.widget.AdapterView.OnItemLongClickListener{@Overridepublic boolean onItemLongClick(AdapterView<?> parent, View view,int position, long id) {setCheckBoxStatue(true);if (mListHScrollView != null) {mListHScrollView.post(new Runnable() {         public void run() {         mListHScrollView.fullScroll(ScrollView.FOCUS_RIGHT);         } }); }return false;}}//控制listView checkbox控件的隐藏和显示protected void setCheckBoxStatue(boolean isVisible){if (isVisible) {for (ItemStatus ItemData: GetItemsExtendData()) {ItemData.mIsCheckBoxSelected = false;ItemData.mIsCheckBoxVisible = true;}}else {for (ItemStatus ItemData: GetItemsExtendData()) {ItemData.mIsCheckBoxSelected = false;ItemData.mIsCheckBoxVisible = false;}}mLongClickStatus = isVisible;refreshListView();}@Overridepublic void finish(){if (mLongClickStatus) {setCheckBoxStatue(false);return;}super.finish();}//手动计算listview的高度private void SetListViewHeightBasedOnChildren(ListView listView) {if (listView == null) return;ListAdapter listAdapter = listView.getAdapter();if (listAdapter == null) return;int nTotalHeight = 0;for (int i = 0; i < listAdapter.getCount(); i++) {View listItem = listAdapter.getView(i, null, listView);listItem.measure(0, 0);nTotalHeight += listItem.getMeasuredHeight();}ViewGroup.LayoutParams params = listView.getLayoutParams();params.height = nTotalHeight + (listView.getDividerHeight()*(listAdapter.getCount()-1));}//设置横向滚动中layout里面textview的宽度private void setTextParams(TextView textView, int col) {if (col == 0)return;textView.setMaxLines(1);textView.setTextSize(14);textView.setPadding(4, 0, 4, 0);textView.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);DisplayMetrics metric = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(metric);int basicScreenWidth = metric.widthPixels; // 屏幕宽度(像素)int basicScreenHeight = metric.heightPixels; // 屏幕高度(像素)int screenWidth = basicScreenWidth - dip2px(this, 60);if (col <= 3) {textView.setWidth(screenWidth / col + 20);} else {if (screenWidth > basicScreenHeight) {if (col > 5) {textView.setWidth(screenWidth / 5 + 10);} else {textView.setWidth(screenWidth / col + 10);}} else {textView.setWidth(screenWidth / 3 + 20);}}}public static int dip2px(Context context, float dpValue) {final float scale = context.getResources().getDisplayMetrics().density;return (int) (dpValue * scale + 0.5f);}}

4、看怎么继承实现上面类的数据接口MainActivity

package com.org.horizontalscrollview;import java.util.ArrayList;import android.os.Bundle;import android.view.View;import android.widget.AdapterView;import android.widget.Toast;public class MainActivity extends CustomListScrollManageActivity {private ArrayList mList = new ArrayList();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);getDataSource();super.initView();}    public ArrayList getDataSource(){    for (int i = 0; i < 20; i++) {    int j = i;        StudentItem item1 = new StudentItem(j, "同学A", "男", 18, "高二");        mList.add(item1);        j ++ ;        StudentItem item2 = new StudentItem(j, "同学B", "女", 17, "高三");        mList.add(item2);}    return mList;    }@Overridepublic ArrayList getReadListHeadItems() {ArrayList headItems = new ArrayList();headItems.add("学号");headItems.add("姓名");headItems.add("性别");headItems.add("年龄");headItems.add("年级");return headItems;}@Overridepublic ArrayList getIndexDataArray(int recordIndex) {ArrayList itemsData = new ArrayList();StudentItem item = new StudentItem();item = mList.get(recordIndex);for (int i = 0; i 
5、主要的是还有一个布局,实现效果关键

<?xml version="1.0" encoding="utf-8"?>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            

此外还有次要的两个listview的item的布局没贴出来,还有一个StudentItem的实体类没贴出来。欢迎留言评论!



更多相关文章

  1. Android(安卓)项目实践(三)——数据库封装
  2. Android(安卓)通过URL scheme 实现点击浏览器中的URL链接,启动特
  3. Android(安卓)AS下的OTG串口设备读写
  4. Android存储和加载本地文件(内部存储设备)
  5. Android(安卓)—— 注解(Annotation)也被称为元数据(Metadata)
  6. 理解 Android(安卓)本地数据存储 API
  7. 【Android】Android(安卓)BLE开发
  8. Android——开发环境简介
  9. Android中Notification的小发现

随机推荐

  1. 关于android的开发环境
  2. Android+OpenCV4开发(一)——Android(安
  3. android 自定义接听电话时报错:java.lang.
  4. RXJava
  5. Android多线程机制和Handler的使用
  6. Starting : Intent{...} Error type 3...
  7. Android的手势操作识别
  8. [Accessibility] Missing contentDescrip
  9. 【Android】getDimension,getDimensionPi
  10. Android显式intent和隐式intent