Android ScrollView与ListView,GridView共处冲突解决方案

Android ScrollView与ListView,GridView共存冲突解决方案

      我们在真实项目中通常会遇到ListView或者GridView嵌套在ScrollView中问题。但是做的时候会发现,一旦两者进行嵌套,即会发生冲突。得不到我们希望的效果。由于ListView和GridView本身都继承于ScrollView,一旦在ScrollView中嵌套ScrollView,那么里面的ScrollView高度计算就会出现问题。我们也就无法得到想要的效果。下面进入正题,我们将分别讨论ScrollView中嵌套ListView和FGridView的情况:

 

     核心解决方案: 重写ListView或者GridView的OnMesure 方法:

   

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		int expandSpec = MeasureSpec.makeMeasureSpec( 
                Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); 
		
		super.onMeasure(widthMeasureSpec, expandSpec);
	}


 

 

    一、ScrollView中嵌套ListView

  BlogScrollViewActivity.java代码:

package com.csdn.blog.scrollview;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;

public class BlogScrollViewActivity extends Activity {
    /** Called when the activity is first created. */
//	MyGridView  grid;
	ImageView image;
	ScrollView scroll;
	String[] texts=new String[]{"无线","通话设置","声音","显示","位置",
			                    "应用","账户","隐私权","存储","语言","游戏","娱乐","电影","音乐",
			                    "辅助功能","日期"};
/*	ArrayAdapter<String> adapter;*/
	TestListView list;
	LinearLayout.LayoutParams lp;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        init();
    }
    void init(){
    	list=(TestListView)findViewById(R.id.list);
    	image=(ImageView)findViewById(R.id.image);
    	list.setAdapter(new GridAdapter(this));
    	scroll=(ScrollView)findViewById(R.id.scroll);
    	scroll.requestChildFocus(image, null);

    }
    private class GridAdapter extends BaseAdapter{

    	Activity context;
    	public GridAdapter(Activity context){
    		this.context=context;
    	}
		@Override
		public int getCount() {
			// TODO Auto-generated method stub
			return texts.length;
		}

		@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) {
			// TODO Auto-generated method stub
			ViewHolder holder=null;
			if(convertView==null){
				convertView=context.getLayoutInflater().inflate(R.layout.item, null);
				holder=new ViewHolder();
				holder.text=(TextView)convertView.findViewById(R.id.grid_text);
				convertView.setTag(holder);
			}
			else{
				holder=(ViewHolder)convertView.getTag();
			}
			holder.text.setText(texts[position]);
			return convertView;
		}
		class ViewHolder {
			TextView text;
		}
    	
    }
}


TestListView.java代码如下:

package com.csdn.blog.scrollview;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View.MeasureSpec;
import android.widget.ListView;

public class TestListView extends ListView{

	public TestListView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}
	public TestListView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}
	public TestListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
	}
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		int expandSpec = MeasureSpec.makeMeasureSpec( 
                Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); 
		
		super.onMeasure(widthMeasureSpec, expandSpec);
	}

}


 

main.xml代码:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="fill_parent"     android:layout_height="fill_parent"     android:orientation="vertical"     android:background="#FFFFFF"     >     <ScrollView         android:layout_height="fill_parent"         android:layout_width="fill_parent"         android:fadingEdgeLength="0dp"         android:scrollbars="none"         android:id="@+id/scroll">         <LinearLayout             android:layout_height="fill_parent"             android:layout_width="fill_parent"             android:orientation="vertical"             >       <ImageView           android:id="@+id/image"           android:layout_height="150dp"           android:layout_width="fill_parent"           android:padding="2dp"           android:scaleType="centerCrop"           android:src="@drawable/fruit"

          />       <com.csdn.blog.scrollview.TestListView           android:id="@+id/list"           android:layout_height="fill_parent"           android:layout_width="fill_parent"           android:fadingEdgeLength="0dp"           android:scrollbars="none"           />         </LinearLayout>     </ScrollView>

</LinearLayout>

 

效果图如下:


     Android ScrollView与ListView,GridView共处冲突解决方案

  这里我的布局方式是上面一张图片,下面放置listView。

  对于此种布局方式,可以通过另外一种方式避免此问题。由于ListView有addHeadView()方法,那么我们可以直接将上面想加入的View通过  getLayoutInflater().inflate(this,R.layout.***) 加入到ListView的顶部即可。

 

  二、ScrollView中嵌套GridView的解决方案。

      ScrollView中嵌套GridView ,最简单的方法就是重写GridView方法,使其在绘制时重新计算GridView高度

     MyGridView.java代码如下:

package com.csdn.blog.scrollview;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.GridView;

public class MyGridView extends GridView{

	public MyGridView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
	}
	public MyGridView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}
	public MyGridView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		int expandSpec = MeasureSpec.makeMeasureSpec( 
                Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); 
        super.onMeasure(widthMeasureSpec, expandSpec); 

	}
}


main.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" 
    android:background="#FFFFFF"
    >
    <ScrollView
        android:layout_height="fill_parent"
        android:layout_width="fill_parent"
        android:fadingEdgeLength="0dp"
        android:scrollbars="none"
        android:id="@+id/scroll">
        <LinearLayout
            android:layout_height="fill_parent"
            android:layout_width="fill_parent"
            android:orientation="vertical"
            >
		    <ImageView
		        android:id="@+id/image"
		        android:layout_height="150dp"
		        android:layout_width="fill_parent"
		        android:padding="2dp"
		        android:scaleType="centerCrop"
		        android:src="@drawable/fruit"

		        />
		    <com.csdn.blog.scrollview.MyGridView
		        android:layout_marginTop="10dp"
		        android:id="@+id/grid"
		        android:layout_height="fill_parent"
		        android:layout_width="fill_parent"
		        android:fadingEdgeLength="0dp"
		        android:scrollbars="none"
		        android:numColumns="3"
		        />
        </LinearLayout>
    </ScrollView>

</LinearLayout>


主类主要就是GridVIew数据绑定。简单贴下代码:

package com.csdn.blog.scrollview;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;

public class BlogScrollViewActivity extends Activity {
    /** Called when the activity is first created. */
	MyGridView  grid;
	ImageView image;
	ScrollView scroll;
	String[] texts=new String[]{"无线","通话设置","声音","显示","位置",
			                    "应用","账户","隐私权","存储","语言","游戏","娱乐","电影","音乐",
			                    "辅助功能","日期"};
	ArrayAdapter<String> adapter;
	LinearLayout.LayoutParams lp;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        init();
    }
    void init(){
    	image=(ImageView)findViewById(R.id.image);
    	grid=(MyGridView)findViewById(R.id.grid);
    	grid.setAdapter(new GridAdapter(this));
    	scroll=(ScrollView)findViewById(R.id.scroll);
    	scroll.requestChildFocus(image, null);

    }
    private class GridAdapter extends BaseAdapter{

    	Activity context;
    	public GridAdapter(Activity context){
    		this.context=context;
    	}
		@Override
		public int getCount() {
			// TODO Auto-generated method stub
			return texts.length;
		}

		@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) {
			// TODO Auto-generated method stub
			ViewHolder holder=null;
			if(convertView==null){
				convertView=context.getLayoutInflater().inflate(R.layout.item, null);
				holder=new ViewHolder();
				holder.image=(ImageView)convertView.findViewById(R.id.grid_image);
				holder.text=(TextView)convertView.findViewById(R.id.grid_text);
				convertView.setTag(holder);
			}
			else{
				holder=(ViewHolder)convertView.getTag();
			}
			holder.image.setImageResource(R.drawable.meinv);
			holder.text.setText(texts[position]);
			return convertView;
		}
		class ViewHolder {
			ImageView image;
			TextView text;
		}
    	
    }
}


   上述代码中  scroll.requestChildFocus(image, null); 此句主要是修复了程序进入时GridView会滑动到顶端的小bug。

   效果图如下:

  Android ScrollView与ListView,GridView共处冲突解决方案