Android 自定义横向滚动条。当你的横向字段或者表格很多时候,显示不下内容,可以使用很想滚动条进行滚动。竖向方面我添加了listview进行添加数据。两者滚动互不干扰。横向滚动条的可以自定义不同的字段的,进行加载就行了。接下来看看效果图,再看代码。
一、效果图
二、自定义MyHScrollView继承HorizontalScrollView
package com.org.scrollview; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.HorizontalScrollView; /* * 自定义的 滚动控件 * 重载了 onScrollChanged(滚动条变化),监听每次的变化通知给 观察(此变化的)观察者 * 可使用 AddOnScrollChangedListener 来订阅本控件的 滚动条变化 * */ public class MyHScrollView extends HorizontalScrollView { ScrollViewObserver mScrollViewObserver = new ScrollViewObserver(); public MyHScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub } public MyHScrollView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } public MyHScrollView(Context context) { super(context); // TODO Auto-generated constructor stub } @Override public boolean onTouchEvent(MotionEvent ev) { Log.i("pdwy","MyHScrollView onTouchEvent"); return super.onTouchEvent(ev); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { /* * 当滚动条移动后,引发 滚动事件。通知给观察者,观察者会传达给其他的。 */ if (mScrollViewObserver != null /*&& (l != oldl || t != oldt)*/) { mScrollViewObserver.NotifyOnScrollChanged(l, t, oldl, oldt); } super.onScrollChanged(l, t, oldl, oldt); } /* * 订阅 本控件 的 滚动条变化事件 * */ public void AddOnScrollChangedListener(OnScrollChangedListener listener) { mScrollViewObserver.AddOnScrollChangedListener(listener); } /* * 取消 订阅 本控件 的 滚动条变化事件 * */ public void RemoveOnScrollChangedListener(OnScrollChangedListener listener) { mScrollViewObserver.RemoveOnScrollChangedListener(listener); } /* * 当发生了滚动事件时 */ public static interface OnScrollChangedListener { public void onScrollChanged(int l, int t, int oldl, int oldt); } /* * 观察者 */ public static class ScrollViewObserver { List<OnScrollChangedListener> mList; public ScrollViewObserver() { super(); mList = new ArrayList<OnScrollChangedListener>(); } public void AddOnScrollChangedListener(OnScrollChangedListener listener) { mList.add(listener); } public void RemoveOnScrollChangedListener( OnScrollChangedListener listener) { mList.remove(listener); } public void NotifyOnScrollChanged(int l, int t, int oldl, int oldt) { if (mList == null || mList.size() == 0) { return; } for (int i = 0; i < mList.size(); i++) { if (mList.get(i) != null) { mList.get(i).onScrollChanged(l, t, oldl, oldt); } } } } }
package com.org.scrollview; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.LinearLayout; /* * * 一个视图容器控件 * 阻止 拦截 ontouch事件传递给其子控件 * */ public class InterceptScrollContainer extends LinearLayout { public InterceptScrollContainer(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } public InterceptScrollContainer(Context context) { super(context); // TODO Auto-generated constructor stub } // // @Override // public boolean dispatchTouchEvent(MotionEvent ev) { // // TODO Auto-generated method stub // //return super.dispatchTouchEvent(ev); // Log.i("pdwy","ScrollContainer dispatchTouchEvent"); // return true; // } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub //return super.onInterceptTouchEvent(ev); Log.i("pdwy","ScrollContainer onInterceptTouchEvent"); return true; //return super.onInterceptTouchEvent(ev); } // @Override // public boolean onTouchEvent(MotionEvent event) { // // TODO Auto-generated method stub // Log.i("pdwy","ScrollContainer onTouchEvent"); // return true; // } }
package com.org.horizontalscrollview; import java.util.ArrayList; import java.util.LinkedList; import com.org.scrollview.MyHScrollView; import com.org.scrollview.MyHScrollView.OnScrollChangedListener; 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.MotionEvent; 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.ListView; 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 LinearLayout mListHead = null; //列表整体标题栏滚动条 private MyHScrollView mHScrollView = null; //是否显示第一列 protected boolean mIsShowTextIndex = true; //listview的适配器 protected ListNumScrollAdapter mAdapter; //整体的根布局 protected int mRootLayout = R.layout.layout_common_sroll; //设置是否支持长按 protected boolean mItemCanLongClick = true; //处于长按状态true,不是长按状态false protected boolean mLongClickStatus = false; //checkbox的状态 protected class ItemStatus { public boolean mIsCheckBoxVisible = false; public boolean mIsCheckBoxSelected = false; } //实例化每一项checkbox的记录列表mItemsExtendData protected LinkedList<ItemStatus> GetItemsExtendData() { if (mItemsExtendData == null) mItemsExtendData = new LinkedList<ItemStatus>(); return mItemsExtendData; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(mRootLayout); } //子类继承后初始化子类数据后,需要调用这个,初始化父类。 protected void initView() { mListHead = (LinearLayout) findViewById(R.id.surfaceManagerListHead); mHScrollView = (MyHScrollView) mListHead.findViewById(R.id.MyHScrollView_head); ListView listItem = (ListView)findViewById(R.id.listViewCommonFeatureItems); //设置表头的触摸滑动事件 mHScrollView.setOnTouchListener(new ListViewAndHeadViewTouchLinstener()); listItem.setOnItemClickListener(new OnItemClickListener()); listItem.setOnItemLongClickListener(new OnItemLongClickListener()); mAdapter = new ListNumScrollAdapter(this); listItem.setAdapter(mAdapter); mListHeadItemsName = getReadListHeadItems(); recreateHeadControl(); initCheckBoxVilible(); setCheckBoxStatue(false); mAdapter.notifyDataSetChanged(); } //加载表头列表数据 protected void recreateHeadControl() { mListHead.setFocusable(true); mListHead.setClickable(true); mListHead.setOnTouchListener(new ListViewAndHeadViewTouchLinstener()); TextView headIndex = (TextView)mListHead.findViewById(R.id.textIndex); setTextParams(headIndex, mListHeadItemsName.size()); headIndex.setText("序号"); headIndex.setVisibility(mIsShowTextIndex == true?View.VISIBLE:View.GONE); LinearLayout layout_items = (LinearLayout)mListHead.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); } } //初始化每一项的CheckBox private void initCheckBoxVilible(){ GetItemsExtendData().clear(); for (int i = 0; i < getItemsCount(); i++) { ItemStatus itemData = new ItemStatus(); // 插入队列 GetItemsExtendData().add(itemData); } } class ListViewAndHeadViewTouchLinstener implements View.OnTouchListener { @Override public boolean onTouch(View arg0, MotionEvent event) { //当在列头 和 listView控件上touch时,将这个touch的事件分发给 ScrollView try { mHScrollView.onTouchEvent(event); } catch (IllegalArgumentException e) { e.printStackTrace(); return false; } return false; } } //抽象接口,列表标题栏 public abstract ArrayList<String> getReadListHeadItems(); //抽象接口,listview整体数据项 public abstract int getItemsCount(); /** * 抽象接口,listview每一项数据的装载,装载返回是 * @param recordIndex * @return ArrayList<String> */ public abstract ArrayList<String> getIndexDataArray(int recordIndex); //////////////////////////////////////////////////////////// //需要每一项编辑或者增加,删除数据的抽象接口,请看具体情况自行添加 /** * listview适配器 * @author Administrator * */ public class ListNumScrollAdapter extends BaseAdapter implements OnCheckedChangeListener { private Context mContext; private LayoutInflater mLayoutInflater; public ListNumScrollAdapter(Context context) { this.mContext = context; mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public int getCount() { Log.e("Show", String.valueOf(getItemsCount())); return getItemsCount(); } @Override public Object getItem(int arg0) { return null; } @Override public long getItemId(int arg0) { return arg0; } @Override public 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, null); viewHolder.hscrollView = (MyHScrollView) view.findViewById(R.id.MyHScrollView_item); viewHolder.headIndex = (TextView)view.findViewById(R.id.textIndex); 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)viewHolder.hscrollView.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; } //列表标题栏,序号数据装载 setTextParams(viewHolder.headIndex, nHeadItemCount); viewHolder.headIndex.setText(String.valueOf(position)); viewHolder.headIndex.setVisibility(mIsShowTextIndex == true ? View.VISIBLE : View.GONE); //每一项横向滚动数据的装载 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); } //表头列表的滚动条事件添加到listview的每一项item mHScrollView.AddOnScrollChangedListener(new OnScrollChangedListenerImp(viewHolder.hscrollView)); return view; } @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { Integer nPosition = (Integer)(buttonView.getTag()); mItemsExtendData.get(nPosition.intValue()).mIsCheckBoxSelected = isChecked; } class OnScrollChangedListenerImp implements OnScrollChangedListener { MyHScrollView mScrollViewArg; public OnScrollChangedListenerImp(MyHScrollView scrollViewar) { mScrollViewArg = scrollViewar; } @Override public void onScrollChanged(int l, int t, int oldl, int oldt) { mScrollViewArg.smoothScrollTo(l, t); } } } //listview的内部类 static class ViewHolder { TextView headIndex; MyHScrollView hscrollView; CheckBox isSelectedCheckBox; } private class OnItemClickListener implements android.widget.AdapterView.OnItemClickListener{ @Override public 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{ @Override public boolean onItemLongClick(AdapterView<?> parent, View view,int position, long id) { setCheckBoxStatue(true); return true; } } //控制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; mAdapter.notifyDataSetChanged(); } @Override public void finish(){ if (mLongClickStatus) { setCheckBoxStatue(false); return; } super.finish(); } //设置横向滚动中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); } }
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>(); @Override protected 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", "男", 17, "高二"); mList.add(item1); j ++ ; StudentItem item2 = new StudentItem(j, "同学B", "女", 17, "高三"); mList.add(item2); } return mList; } @Override public ArrayList<String> getReadListHeadItems() { ArrayList<String> headItems = new ArrayList<String>(); headItems.add("学号"); headItems.add("姓名"); headItems.add("性别"); headItems.add("年龄"); headItems.add("年级"); return headItems; } @Override public 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; } @Override public int getItemsCount() { return mList.size(); } }
<?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/surfaceManagerListHead" 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.InterceptScrollContainer android:id="@+id/scroollContainter" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:focusable="false" > <com.org.scrollview.MyHScrollView android:id="@+id/MyHScrollView_head" 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.MyHScrollView> </com.org.scrollview.InterceptScrollContainer> <FrameLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginRight="15dp" android:visibility="gone" > <CheckBox android:id="@+id/checkBoxIsSelected" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:visibility="invisible" /> </FrameLayout> </LinearLayout> </LinearLayout> <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:orientation="vertical" > <ListView android:id="@+id/listViewCommonFeatureItems" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView> </LinearLayout> </RelativeLayout> </LinearLayout> </FrameLayout> </LinearLayout>
这些选中的状态都有记下来了,后期你想怎么用就怎么用。到了这里就结束了,欢迎交流学习。
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/qq_16064871/article/details/48929867