`
alian008580101
  • 浏览: 23180 次
社区版块
存档分类

自定义GridView以解决ScrollView嵌套Android自身GridView出现的疑难问题

阅读更多

Android开发中偶尔会遇到ScrollView嵌套GridView情景,但是谷歌官网是不推荐这种方式的,因为他们都有滚动条,嵌套使用会有冲突,无奈只能另谋他路,自定义个仿GridView的控件

1.定义attrs.xml文件

<declare-styleable name="GridLinearLayout">
        <attr name="verticalSpace" format="dimension"/>
        <attr name="horizontalSpace" format="dimension"/>
        <attr name="rows" format="integer"/>
        <attr name="columns" format="integer"/>
</declare-styleable>

 2.定义GridLinearLayout文件

/**
 * 一个没有滚动条的LinearLayout,但是却很像GridView。
 * 实际上,就是为了解决当GridView被包含在一个SrcollView中而却拥有两个滚动条相互排斥而做。
 */
public class GridLinearLayout extends LinearLayout{
	/**仿GridView单元格适配器*/
	private BaseAdapter adapter;
	/**仿GridView列数*/
	private int columns=1;
	/**仿GridView行数*/
	private int rows=1;
	/**仿GridView填充的单元格总数*/
	private int count;
	/**仿GridView单元格单击事件*/
	private OnCellClickListener onCellClickListener;
	/**布局水平分割线宽度*/
	private int horizontalSpace =1;
	/**布局垂直分割线宽度*/
	private int verticalSpace =1;
	/**
	 * 仿GridView构造方法
	 * @param context
	 */
	public GridLinearLayout(Context context) {
		super(context);
	}

	/**
	 * 仿GridV构造方法
	 * @param context
	 * @param attrs
	 */
	public GridLinearLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		initAttrs(context, attrs);
	}

	/***
	 * 加载xml文件设置的属性值
	 * @param context
	 * @param attrs
	 */
	private void initAttrs(Context context ,AttributeSet attrs){
		TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.GridLinearLayout);
		columns = typedArray.getInteger(R.styleable.GridLinearLayout_columns, 1);
		rows = typedArray.getInteger(R.styleable.GridLinearLayout_rows, 1);
		horizontalSpace = typedArray.getDimensionPixelSize(R.styleable.GridLinearLayout_horizontalSpace, 0);
		verticalSpace = typedArray.getDimensionPixelSize(R.styleable.GridLinearLayout_verticalSpace, 0);
		typedArray.recycle();
	}
	
	/**
	 * 构造水平显示LinearLayout用于填充cell
	 * @return
	 */
	private LinearLayout rowLinearLayout(){
		LinearLayout itemLinearLayout = new LinearLayout(getContext());
		itemLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
		itemLinearLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
		itemLinearLayout.setGravity(Gravity.LEFT);
		return itemLinearLayout;
	}
	
	
	/**
	 * 仿GridView将适配器单元格绑定到当前LinearLayout中
	 * @return
	 */
	public void bindLinearLayout() {
		removeAllViews();
		rows = getSpecialRows(true);
		if(rows==-1){
			return;
		}
		for(int r=0;r<rows;r++){
			LinearLayout itemRow = rowLinearLayout();
			for(int c=0;c<columns;c++){
				final int index = r*columns+c;
				View cellView = adapter.getView(index, null, null);
				cellView.setLayoutParams(cellLayoutParams(index));
				if(index<count||index==(count-1)){
					itemRow.addView(cellView,c);
					cellView.setOnClickListener(new OnClickListener() {
						@Override
						public void onClick(View v) {
							if(onCellClickListener!=null){
								onCellClickListener.onCellClick(index);
							}
						}
					});
					
					if(index==(count-1)){
						addView(itemRow, r);
						return;
					}
				}else{
					return;
				}
			}
			addView(itemRow, r);
		}
	}
	
	/**
	 * 获取屏幕宽度用于均分一行LinearLayout各个Cell
	 * @return
	 */
	@SuppressWarnings("deprecation")
	private int screenWidth(){
		/*Point outSize = new Point();
		WindowManager windowManager = (WindowManager) getContext().getSystemService(Service.WINDOW_SERVICE);
		Display display = windowManager.getDefaultDisplay();
		display.getSize(outSize);
		return outSize.x;*/
		
		int screenWidth;
		WindowManager windowManager = (WindowManager) getContext().getSystemService(Service.WINDOW_SERVICE);
		Display display = windowManager.getDefaultDisplay();
		screenWidth = display.getWidth();
		return screenWidth;
	}
	
	/**
	 * 设置当前单元格边距,
	 * 每一行第一个左边距为0底边距为horizontalSpace,
	 * 其他单元格左边距为verticalSpace底边距为horizontalSpace
	 * @param index 单元格序数
	 * @return
	 */
	private LayoutParams cellLayoutParams(int index){
		LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(cellWidth(),LayoutParams.WRAP_CONTENT);
		if(index%columns==0){
			params.setMargins(0, 0, 0, horizontalSpace);
			return params;
		}else{
			params.setMargins(verticalSpace, 0, 0, horizontalSpace);
			return params;
		}
	}
	
	/***
	 * 计算单元格宽度
	 * @return
	 */
	private int cellWidth(){
		int cellScreenWidth = screenWidth()-(columns-1)*verticalSpace;
		return cellScreenWidth/columns;
	}
	
	/***
	 * 是否按列的倍数返回行数
	 * @param isSpecial TRUE:返回列的倍数行数,FALSE:有多少行显示多少行
	 * @return 返回-1时表示列数为0
	 */
	private int getSpecialRows(boolean isSpecial){
		try {
			if(isSpecial){
				return count/columns;
			}else{
				return (int) Math.ceil((double)count/columns);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return -1;
		}
	}
	
	/***
	 * 返回该控件的适配器
	 * @return
	 */
	public BaseAdapter getAdapter() {
		return adapter;
	}

	/**
	 * 设置该控件的适配器
	 * @param adapter 自定义适配器
	 */
	public void setAdapter(BaseAdapter adapter) {
		this.adapter = adapter;
		this.count = adapter.getCount();
	}

	/**
	 * 返回该控件的列数
	 * @return
	 */
	public int getColumns() {
		return columns;
	}

	/**
	 * 设置该控件的列数
	 * @param columns 列数
	 */
	public void setColumns(int columns) {
		this.columns = columns;
	}

	/**
	 * 返回该控件的行数
	 * @return
	 */
	public int getRows() {
		return rows;
	}

	/**
	 * 设置该控件的行数
	 * @param rows 行数
	 */
	public void setRows(int rows) {
		this.rows = rows;
	}

	/**
	 * 返回该控件各单元格水平间距
	 * @return
	 */
	public int getHorizontalSpace() {
		return horizontalSpace;
	}

	/**
	 * 设置该控件各单元格水平间距
	 * @param horizontalSpace 间距
	 */
	public void setHorizontalSpace(int horizontalSpace) {
		this.horizontalSpace = horizontalSpace;
	}

	/**
	 * 返回该控件各单元格垂直间距
	 * @return
	 */
	public int getVerticalSpace() {
		return verticalSpace;
	}

	/**
	 * 设置该控件各单元格垂直间距
	 * @param verticalSpace 间距
	 */
	public void setVerticalSpace(int verticalSpace) {
		this.verticalSpace = verticalSpace;
	}

	public interface OnCellClickListener{
		public void onCellClick(int index);
	}
	
	/**
	 * 监听响应单元格单击事件
	 * @param onCellClickListener 单元格单击事件接口
	 */
	public void setOnCellClickListener(OnCellClickListener onCellClickListener){
		this.onCellClickListener = onCellClickListener;
	}
}

 3.可以将此控件嵌套在ScrollView中,然后调用方式如下

//获取控件
glFriendRecommendTask = (GridLinearLayout) view.findViewById(R.id.glFriendRecommendTask);
//设置控件适配器,适配器按正常方式定义即可
glFriendRecommendTask.setAdapter(friendRecommendTaskAdapter);
//如果需要监听适配器中的单击事件可在此处触发						glFriendRecommendTask.setOnCellClickListener(new OnCellClickListener() {
								@Override
								public void onCellClick(int index) {
									
								}
							});
//设置该控件显示的列数							glFriendRecommendTask.setColumns(3);
//最后调用绑定方法即可							glFriendRecommendTask.bindLinearLayout();

 

 

0
0
分享到:
评论
2 楼 chaozhidan 2016-02-29  
楼主有demo么,为什么我的显示不出来呢,646869341@qq.com,谢谢
1 楼 吝啬你的温柔 2016-01-02  
没用用过吗?

相关推荐

    ScrollView嵌套GridView不能滚动的问题解决方案

    在上面的布局文件中,我们使用了自定义的 MyGridView 控件来代替原来的 GridView 控件,从而解决了 ScrollView 嵌套 GridView 不能滚动的问题。 解决 ScrollView 嵌套 GridView 不能滚动的问题的关键是重写 ...

    Android ScrollView嵌套ListView嵌套GridView的上下拉以及加载更多

    然而,由于ScrollView自身并不支持滚动事件的监听,因此当我们在ScrollView中嵌套可滚动的组件如ListView或GridView时,可能会遇到滚动冲突问题。为了解决这个问题,开发者需要手动处理滚动事件,或者选择使用如...

    Android ScrollView 嵌套解决方案

    首先,理解ScrollView的基本工作原理是解决问题的关键。ScrollView本质上是一个线性布局(LinearLayout)的扩展,它可以容纳一个或多个子视图,并允许用户滚动查看超出屏幕范围的内容。当一个ScrollView包含另一个...

    Android 中ScrollView嵌套GridView.rar_GridView android_android_scrol

    解决这个问题的方法是自定义一个ScrollView,重写onInterceptTouchEvent()方法,让ScrollView只处理垂直方向的滑动,将水平滑动事件传递给内部的GridView。 具体步骤如下: 1. 创建一个新的ScrollView子类,比如...

    scrollview嵌套问题总汇

    本篇文章将详细探讨“ScrollView嵌套问题总汇”,包括S嵌L(ScrollView嵌套ListView)、S嵌G(ScrollView嵌套GridView)、S嵌S(ScrollView嵌套ScrollView)、H嵌G(HorizontalScrollView嵌套GridView)以及S嵌(H嵌G...

    ScrollView嵌套listView、GridView时滑动冲突

    1、ScrollView嵌套listView、GridView时滑动冲突,自定义 ListView、GridView; 2、自定义ScrollView,解决 当有横向的滑动操作时,与ScrollView上下滑动冲突; 2、横向ListView

    Android中ScrollView嵌套GridView显示不全解决方法

    在Android开发中,有时我们需要在一个页面中展示大量的数据,这时可能会使用ScrollView来实现滚动效果,同时内部嵌套一个GridView以实现列表布局。然而,当ScrollView和GridView组合使用时,经常会出现显示不全的...

    解决ScrollView嵌套ListView问题的几种方案

    总的来说,解决ScrollView嵌套ListView问题需要根据具体应用场景选择合适的方法。NestedScrollView、RecyclerView、HeaderView以及自定义ViewGroup都是有效的策略,开发者应根据项目需求和性能考虑来选择最佳方案。...

    android 自定义gridView 按日期显示图片和视频 galleryDemo

    android 自定义gridView 按日期显示图片和视频 galleryDemo android 自定义gridView 按日期显示图片和视频 galleryDemo android 自定义gridView 按日期显示图片和视频 galleryDemo 免费下载 给个好评!

    自定义gridview实现

    希望有帮助,我自己摸索一段时间的来的,比较简单一个类就可以实现,添加使用内部类的方法

    ScrollView,嵌套ListView,ListView并同时嵌套GridView

    总之,嵌套ScrollView、ListView和GridView需要开发者对Android视图系统有深入理解,合理使用这些组件可以创建出复杂而功能丰富的用户界面,但同时也需要妥善处理可能出现的滚动冲突和性能问题。在实际项目中,应该...

    解决scrollView和gridView和ListView嵌套的冲突

    总的来说,解决ScrollView与GridView和ListView嵌套冲突的关键在于合理规划布局,选择合适的组件,以及进行必要的自定义和优化。通过以上方法,我们可以实现良好的用户体验,同时避免滚动冲突带来的问题。在实际开发...

    自定义的各种风格gridview

    在Android开发中,GridView是一种非常常见的布局控件,它允许我们以网格的形式展示数据,通常用于创建像照片墙、应用列表等界面。本教程将深入探讨如何自定义各种风格的GridView,包括刷新、加载和横向展示等特性。 ...

    Android编程开发之ScrollView嵌套GridView的方法

    总之,Android开发中ScrollView嵌套GridView的问题是一个常见的挑战,通过自定义GridView或使用更现代的滚动组件,我们可以有效地解决这个问题,确保用户能够完整地浏览所有内容。同时,持续关注Android API的更新和...

    解决GridView和ScrollView冲突问题

    为了解决这个问题,我们通常需要自定义一个继承自 GridView 的类,重写其中的部分方法以适应在 ScrollView 内部使用的需求。以下是一些关键步骤: 1. **创建自定义 GridView 类**: 首先,创建一个新的类,如 `...

    ScrollView嵌套listview或gridview

    当ScrollView中嵌套ListView或者GrideView时,listView和GrideView不能完全显示的时候

    Android最简单的gridview嵌套gridview,解决滑动冲突问题

    本主题聚焦于如何在Android应用中实现一个"最简单的gridview嵌套gridview"的场景,并解决滑动冲突问题。 首先,让我们了解一下GridView的基本概念。GridView是一种布局管理器,它将视图(如图片、文字等)以网格的...

    深入解析ScrollView嵌套GridView显示不全问题及解决方案

    在某些情况下,仅仅通过设置 `padding` 或调整滚动行为可能无法完全解决问题。这时候,使用自定义 Adapter 可以提供更加灵活的方式来控制 GridView 的布局。 **自定义 Adapter 示例** ```java public class ...

    Android书架(自定义GridView)

    在Android开发中,"Android书架(自定义GridView)"是一个常见的应用场景,通常用于实现类似电子书库或图书展示的功能。书架效果是通过自定义GridView来达成的,因为GridView是一种可以灵活展示多行多列数据的视图...

Global site tag (gtag.js) - Google Analytics