热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

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

前一段时间写了一个自定义横向滚动条,感觉效果不怎样好(Android自定义横向滚动条)。又开始改善结构,使用setScrollView写了一个联动进阶版。标题的滚动条和内容

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

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,不是长按状态false
	protected boolean mLOngClickStatus= false;
	//右边的listview
	protected ListView mrightListView;
	//左边的listview
	protected ListView mleftListView;
	//整体的根布局
	protected int mRootLayout = R.layout.layout_common_sroll;
	
	//checkbox的状态
	protected class ItemStatus {
		public boolean mIsCheckBoxVisible = false;
		public boolean mIsCheckBoxSelected = false;
	}
	
	//实例化每一项checkbox的记录列表mItemsExtendData
	protected LinkedList GetItemsExtendData() {
		if (mItemsExtendData == null) mItemsExtendData = new LinkedList();
		return mItemsExtendData;
	}
	
	@Override
	protected 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  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);
		}
		
		@Override
		public int getCount() {
			return getItemsCount();
		}

		@Override
		public Object getItem(int position) {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public long getItemId(int position) {
			// TODO Auto-generated method stub
			return 0;
		}

		@Override
		public 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);
		}
		
		@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_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  itemsData = getIndexDataArray(position);
			for(int i=0; i  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);
			
			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();
	}
	
	@Override
	public 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  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();

	@Override
	protected 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;
    }
	
	@Override
	public ArrayList getReadListHeadItems() {
		ArrayList headItems = new ArrayList();
		headItems.add("学号");
		headItems.add("姓名");
		headItems.add("性别");
		headItems.add("年龄");
		headItems.add("年级");
		return headItems;
	}
	
	@Override
	public ArrayList getIndexDataArray(int recordIndex) {
		ArrayList itemsData = new ArrayList();
		StudentItem item = new StudentItem();
		item = mList.get(recordIndex);
		for (int i = 0; i  
 
5、主要的是还有一个布局,实现效果关键




    


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




推荐阅读
  • 本文实例讲述了Android编程实现读取工程中的txt文件功能。分享给大家供大家参考,具体如下:1.众所周知,Android的res文件夹 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讲述了如何通过代码在Android中更改Recycler视图项的背景颜色。通过在onBindViewHolder方法中设置条件判断,可以实现根据条件改变背景颜色的效果。同时,还介绍了如何修改底部边框颜色以及提供了RecyclerView Fragment layout.xml和项目布局文件的示例代码。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 在开发app时,使用了butterknife后,在androidStudio打包apk时可能会遇到报错。为了解决这个问题,可以通过打开proguard-rules.pro文件进行代码混淆来解决。本文介绍了具体的混淆代码和方法。 ... [详细]
  • Tkinter Frame容器grid布局并使用Scrollbar滚动原理
    本文介绍了如何使用Tkinter实现Frame容器的grid布局,并通过Scrollbar实现滚动效果。通过将Canvas作为父容器,使用滚动Canvas来滚动Frame,实现了在Frame中添加多个按钮,并通过Scrollbar进行滚动。同时,还介绍了更新Frame大小和绑定滚动按钮的方法,以及配置Scrollbar的相关参数。 ... [详细]
  • mui框架offcanvas侧滑超出部分隐藏无法滚动如何解决
    web前端|js教程off-canvas,部分,超出web前端-js教程mui框架中off-canvas侧滑的一个缺点就是无法出现滚动条,因为它主要用途是设置类似于qq界面的那种格 ... [详细]
  • 涉及的知识点-ViewGroup的测量与布局-View的测量与布局-滑动冲突的处理-VelocityTracker滑动速率跟踪-Scroller实现弹性滑动-屏幕宽高的获取等实现步 ... [详细]
  • setMeasuredDimension(x,y);导致出错-------------布局文件没设置背景颜色导致onMeasure()测量-----如果不执行setMeasu ... [详细]
author-avatar
luomo
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有