GridView学习

来源:互联网 发布:淘宝 买飞机 编辑:程序博客网 时间:2024/06/01 09:48

(1)GridView学习总结

GridView使用上和ListView十分相似。

GridViewmGridView=(GridView)findViewById(R.id.gridview);

CustomAdaptermAdapter=newCustomAdapter(MainActivity.this,R.layout.item,List<Custom>);

mGridView.setAdaper(mAdapter);

我们需要先思考,在res/layout目录下建立一个item.xml。它代表着ListView或者GridView中每一部分的布局。

我们需要自定义两个类,一个是Custom.一个是适配器CustomAdapter(要继承于ArrayAdapter)

先说item.xml

假设需要一个TextView和一个Button

<?xmlversion="1.0"encoding="utf-8"?>

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

<TextView

android:id="@+id/textview"

android:layout_width="match_parent"

android:layout_height="wrap_content"

/>

<Button

android:id="@+id/button"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:background="@drawable/newbutton"/>


</LinearLayout>


先说Custom它的成员变量要与item.xml需要的自定义的属性一一对应。

publicclass Custom{

privateString textName; //对应item.xml中的TextView的文字内容

privateButton buttonName;//对应item.xml中的Button的文字内容

//使用带形参的构造方法,直接可以在初始化类的时候给成员变量赋值。

publicCustom(String textName,String buttonName){

this.textName=textName;

this.buttonName=buttonName;

}

//提供若干get方法方便其他类获取到Custom类的相关属性

publicString getTextName(){

returntextName;

}

publicString getButtonName(){

returnbuttonName;

}


}


再说CustomAdapter

publicclass CustomAdapter extends ArrayAdapter<Custom>{

privateint resouceId;//这个resouceId指的就是item.xmlid。就是R.layout.item.

PublicCustomAdapter(Context context,int resource,List<Custom>objects){

super(context,resource,objects);

resourceId=resource;

}

//getView方法主要是给item.xml的各个控件赋予属性值

publicView getView(int position, ViewconvertView, ViewGroup parent) {

//TODOAuto-generated method stub

StringtextName=getItem(position).getTextName();//getItem()方法返回List<Custom>Custom对象

StringbuttonName=getItem(position).getButtonName();

LayoutInflatermInflater=LayoutInflater.from(getContext());

Viewview=mInflater.inflate(resourceId,null);

TextViewmTextView=(TextView)view.findViewById(R.id.textview);

ButtonmButton=(Button)view.findViewById(R.id.button);

mTextView.setText(textName);

mButton.setText(buttonName);

returnview;

}


}

最后MainActivity

List<Custom>mList = newArrayList<Custom>();

GridViewmGridView;

mGridView= (GridView) findViewById(R.id.shit);

CustomAdaptermAdapter = newCustomAdapter(MainActivity.this,R.layout.item,mList);

init();

mGridView.setAdapter(mAdapter);

(2)ListViewGridView的点击事件

根据形参intpositon可以获取到数组或者集合的位置。

mListView1.setOnItemClickListener(newOnItemClickListener() {

@Override

publicvoidonItemClick(AdapterView<?> parent, View view,intposition,longid) {

//TODOAuto-generated method stub

if(mStrings[position].equals("onlytext")){

Toast.makeText(MainActivity.this,"notprovide",Toast.LENGTH_SHORT).show();

}

if(mStrings[position].equals("textand pictore")){

IntentmIntent=newIntent();

mIntent.setClass(MainActivity.this,FirstActivity.class);

startActivity(mIntent);

}

if(mStrings[position].equals("customview")){

}

Log.e("AdapterView<?>",parent + "");

Log.e("View",view + "");

Log.e("position",position + "");

Log.e("id",id + "");

}

});

(3)GridView,ListView探索。

GridView,ListView均继承于AbsListViewAbsListView重写了onTouchEvent方法。

首先明确GridView是容器。我们自定义的item假设是一个RelativeLayout中放一个Button.一般容器是默认不拦截事件的。所以事件会从GridView分发到RelativeLayout然后到Button.因为Button默认clickabletrue.导致ButtononTouchEvent返回true,进而导致ButtondispatchTouchEvent返回true.不会执行容器的dispatchTouchEvent.而我们想要调用GridViewsetOnItemClickListener这个方法。我们需要让事件分发到GridView.我们可以把GridView的每个部分理解成A容器--B容器--C组件。也就是要让事件分发到A容器。

所以我们把Buttonandroid:clickable属性设置为false.默认ButtonlongClickable属性也是false.默认onTouch方法也是返回false.

此时事件从C组件分发到B容器,B容器是我们用的 RelativeLayoutorLinearLayout.不设置监听事件的话,会继续分发到A容器。

我们发现此时GridViewsetOnItemClickListener依然没有生效。原因是因为GridViewListView继承的AbsListView重写了onTouchEvent.

查看源码,可以发现AbsListViewonTouchEvent

publicbooleanonTouchEvent(MotionEvent ev) {

.

caseMotionEvent.ACTION_UP:{

onTouchUp(ev);

break;

.

}


privatevoidonTouchUp(MotionEvent ev) {

.

if(inList && !child.hasFocusable()) {

if(mPerformClick==null){

mPerformClick=newPerformClick();

}

.

if(!mDataChanged && mAdapter.isEnabled(motionPosition)){

mTouchMode=TOUCH_MODE_TAP;

setSelectedPositionInt(mMotionPosition);

layoutChildren();

child.setPressed(true);

positionSelector(mMotionPosition,child);

setPressed(true);


..

mTouchModeReset=newRunnable() {

@Override

publicvoidrun() {

mTouchModeReset=null;

mTouchMode=TOUCH_MODE_REST;

child.setPressed(false);

setPressed(false);

if(!mDataChanged && isAttachedToWindow()) {

performClick.run();

}

}

};

.

}

...}


源码中标示出!child.hasFocusable()要为true才能响应点击事件。也就是B容器,C组件不能获得焦点。

所以想要事件分发到A容器。我们还要把Buttonandroid:focusable属性设置为false.B容器默认focusablefalse.(待确认下,应该是的)

也就是Button中以下属性要确认,clickablefalse,longClickabelfalse,focusablefalse.

我们发现可以响应GridViewsetOnItemClickListener后,但是C组件竟然也有按下和释放的效果了。

明明我们在设置clickablefalse,longClickabelfalse后就应该Button无法点击,一直处于未点击的效果不变的。

原因是源码中有child.setPressed(true)child.setPressed(false).

而且源码中有setPressed(true)setPressed(false).

所以A容器,B容器,C组件(可以是多个,已经验证,但要设置好让事件分发到A容器)都会有按下和释放的效果,如果你有设置。

(4)GridView高度自适应

1.GridView对象送到Adapter中。

2.AdaptergetView中获取到GridView的高度。

3.GridView的高度除以n得到n部分的高度。

4.将每部分的高度设置给item.

classCustomAdapterextendsArrayAdapter<FunctionItem> {

privateintresourceId;

GridViewmm;

publicCustomAdapter(Context context, intresource,

List<FunctionItem>objects,GridView gridView) {

super(context,resource, objects);

resourceId= resource;

mm=gridView;

//TODOAuto-generated constructor stub

}


publicView getView(intposition, View convertView, ViewGroup parent) {

//TODOAuto-generated method stub

LayoutInflatermInflater = LayoutInflater.from(getContext());

Viewview = mInflater.inflate(resourceId,null);

ViewmView=(View)view.findViewById(R.id.item_rel);

LayoutParamsmLayoutParams=mView.getLayoutParams();

mLayoutParams.height=mm.getHeight()/3-4;

returnview;

}

(5)GridView,ListViewandroid:descendantFocusability属性

android:descendantFocusability=“xxx”

xxx可以为:

beforeDescendantsviewgroup会优先其子类控件而获取到焦点

afterDescendantsviewgroup只有当其子类控件不需要获取焦点时才获取焦点

blocksDescendantsviewgroup会覆盖子类控件而直接获得焦点

项目中的listview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承BaseAdapter,在adapter中按照需求进行编写,问题就出现了,可能会发生点击每一个item的时候没有反应,无法获取的焦点。原因多半是由于在你自己定义的Item中存在诸如ImageButtonButtonCheckBox等子控件(也可以说是Button或者Checkable的子类控件),此时这些子控件会将焦点获取到,所以常常当点击item时变化的是子控件,item本身的点击没有响应。

找时间写个demo三个都试试。一般应该第一个和第三个用的多。应该就是与事件分发有关,之前解决过GridView的点击问题的。

实测,这个属性并不是写在listView控件中的,而是ListView对应的item.xml的容器中的。切记


原创粉丝点击