Android 自定义横向滚动条联动进阶版

来源:互联网 发布:淘宝网客户关系管理 编辑:程序博客网 时间:2024/06/05 08:52

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

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<String> mListHeadItemsName = new ArrayList<String>();//每一项checkbox的记录列表protected LinkedList<ItemStatus> 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<ItemStatus> GetItemsExtendData() {if (mItemsExtendData == null) mItemsExtendData = new LinkedList<ItemStatus>();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<String> getReadListHeadItems();//抽象接口,listview整体数据项public abstract int getItemsCount();/** * 抽象接口,listview每一项数据的装载,装载返回是 * @param recordIndex * @return  ArrayList<String> */public abstract ArrayList<String> 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<String> 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<StudentItem> mList = new ArrayList<StudentItem>();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);getDataSource();super.initView();}    public ArrayList<StudentItem> 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<String> getReadListHeadItems() {ArrayList<String> headItems = new ArrayList<String>();headItems.add("学号");headItems.add("姓名");headItems.add("性别");headItems.add("年龄");headItems.add("年级");return headItems;}@Overridepublic ArrayList<String> getIndexDataArray(int recordIndex) {ArrayList<String> itemsData = new ArrayList<String>();StudentItem item = new StudentItem();item = mList.get(recordIndex);for (int i = 0; i <mList.size(); i++) {itemsData.add(String.valueOf(item.getmMunber()));itemsData.add(item.getmName());itemsData.add(item.getmSex());itemsData.add(String.valueOf(item.getmAge()));itemsData.add(item.getmGrade());}return itemsData;}@Overridepublic int getItemsCount() {return mList.size();}}

5、主要的是还有一个布局,实现效果关键

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/layoutProgramManagerMainView"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <FrameLayout        android:layout_width="match_parent"        android:layout_height="match_parent" >        <LinearLayout            android:layout_width="match_parent"            android:layout_height="match_parent"            android:orientation="vertical" >            <LinearLayout                android:id="@+id/HeadListLayout"                android:layout_width="match_parent"                android:layout_height="48dp"                android:background="#F5FFFA"                android:orientation="vertical" >                <LinearLayout                    android:layout_width="match_parent"                    android:layout_height="match_parent"                    android:divider="@drawable/driver"                    android:paddingRight="10dp"                    android:showDividers="middle" >                    <TextView                        android:id="@+id/textIndex"                        android:layout_width="60dp"                        android:layout_height="match_parent"                        android:gravity="center_vertical"                        android:textAppearance="?android:attr/textAppearanceMedium"                        android:textColor="#218868"                        android:textSize="13dp" />                    <com.org.scrollview.SyncHorizontalScrollView                        android:id="@+id/listHeadHScrollView"                        android:layout_width="match_parent"                        android:layout_height="match_parent"                        android:focusable="false"                        android:scrollbars="none" >                        <LinearLayout                            android:layout_width="match_parent"                            android:layout_height="match_parent" >                            <LinearLayout                                android:id="@+id/layoutTextHeadItems"                                android:layout_width="match_parent"                                android:layout_height="match_parent"                                android:layout_weight="1"                                android:divider="@drawable/driver"                                android:focusable="false"                                android:gravity="center_vertical"                                android:orientation="horizontal"                                android:showDividers="middle" >                            </LinearLayout>                        </LinearLayout>                    </com.org.scrollview.SyncHorizontalScrollView>                </LinearLayout>            </LinearLayout>            <ScrollView                android:layout_width="match_parent"                android:layout_height="match_parent"                android:fillViewport="true" >                <LinearLayout                    android:layout_width="match_parent"                    android:layout_height="match_parent"                    android:orientation="vertical" >                    <RelativeLayout                        android:layout_width="match_parent"                        android:layout_height="0dp"                        android:layout_weight="1" >                        <LinearLayout                            android:layout_width="match_parent"                            android:layout_height="match_parent"                            android:divider="@drawable/driver"                            android:orientation="horizontal"                            android:showDividers="middle" >                            <LinearLayout                                android:layout_width="60dp"                                android:layout_height="match_parent"                                android:divider="@drawable/driver"                                android:orientation="vertical"                                android:showDividers="end" >                                <ListView                                    android:id="@+id/leftListView"                                    android:layout_width="match_parent"                                    android:layout_height="wrap_content" >                                </ListView>                            </LinearLayout>                            <com.org.scrollview.SyncHorizontalScrollView                                android:id="@+id/listRightHScrollView"                                android:layout_width="match_parent"                                android:layout_height="wrap_content"                                android:scrollbars="@null" >                                <LinearLayout                                    android:layout_width="match_parent"                                    android:layout_height="match_parent"                                    android:orientation="vertical" >                                    <ListView                                        android:id="@+id/rightListView"                                        android:layout_width="match_parent"                                        android:layout_height="wrap_content" >                                    </ListView>                                </LinearLayout>                            </com.org.scrollview.SyncHorizontalScrollView>                        </LinearLayout>                    </RelativeLayout>                </LinearLayout>            </ScrollView>        </LinearLayout>    </FrameLayout></LinearLayout>

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



2 0
原创粉丝点击