刚刚做了一个项目,是做应用墙相关的,就是把一个个应用的图标和名称显示到GridView中。本来想着,像GridView这样常用成熟的控件,使用应该非常的简单,但真正在项目中实现起来,就有各种各样的小问题,其中一个就是不能适配所有的手机型号。
下面就讲解我项目中使用的适配方法,或许不是最好的,如果那位大神有更好的方法,望指点~~
一开始,只是简单的布局GridView,把GridView的列数指定为4列。GridView布局如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <GridView android:id="@+id/gridView" android:layout_width="match_parent" android:layout_height="match_parent" android:horizontalSpacing="10dp" android:numColumns="4" android:verticalSpacing="10dp" > </GridView> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:id="@+id/app_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" > </ImageView> <TextView android:id="@+id/app_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/app_icon" android:layout_centerHorizontal="true" > </TextView> </RelativeLayout>
显示的结果如下:
看上面效果图,在不同分辨率的手机显示,同样是四列,但效果差别非常大。
这是为什么??
这个不难解释,获取的图片资源是一样的, 但手机的分辨率不一样,显示是按图片大小进行自适应的(即ImageView设置wrap_content),所以就出现了上面的现象,那怎么办呢??
但深究,就会发现,固定大小真的可以吗?比如手机的屏幕大小为480dp,而设置ImageView的宽度为100dp, 那么480/100=4 余80, 那剩下的80dp怎么办?
其实Android早想到了, 而且提供了很好的解决办法:不设置GridView列的固定值,而是设置列的最小值,然后根据最小值决定分成列数,最后把剩余的平均分配给列或者列之间的间隙。如,上面把列的最小值设为100dp,那么480/100=4即可以分成4列,最后剩余的80dp可以平均分配给4列,那么最终为4列,每列120dp。
下面为上面说明的布局:
android:columnWidth="100dp" 设置每列最小宽度
android:numColumns="auto_fit" 列数自适配,系统会根据上面的列宽计算列数
android:stretchMode="columnWidth" 剩余的平均分配给列,当然也可以平均分配给列之间的间隙。
于是,我的GridView的布局如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="15dp" android:layout_marginRight="15dp" android:background="#DCDCDC" android:orientation="vertical" > <GridView android:id="@+id/gridView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:columnWidth="@dimen/gridview_column_width" android:gravity="center" android:horizontalSpacing="10dp" android:numColumns="auto_fit" android:stretchMode="columnWidth" android:verticalSpacing="10dp" > </GridView> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:id="@+id/app_icon" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitXY" > </ImageView> <TextView android:id="@+id/app_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/app_icon" android:layout_centerHorizontal="true" > </TextView> </RelativeLayout>
效果图看出,图片的宽度是合理了,但是高度不合适,高度还是图片实际高度,所以出现拉伸。
回看上面的GridView 的布局,可以看出我们只是规定了宽度的大小,而没有对高度进行设置,当然就是这样的效果了。
那应该怎样设置Item中ImageView的高度? 我没有找到Android提供的直接的方法,那就只能 自己来了。
给控件设定大小,想到的自然是自定义控件里面的onMeasure()方法了,也很简单,在onMeasure里面把宽高设置相等即可,直接上代码:
package com.mobisummer.ads.wall; import android.content.Context; import android.util.AttributeSet; import android.widget.RelativeLayout; public class SquareLayout extends RelativeLayout { public SquareLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public SquareLayout(Context context, AttributeSet attrs) { super(context, attrs); } public SquareLayout(Context context) { super(context); } @SuppressWarnings("unused") @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // For simple implementation, or internal size is always 0. // We depend on the container to specify the layout size of // our view. We can't really know what it is since we will be // adding and removing different arbitrary views and do not // want the layout to change as this happens. setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec)); // Children are just made to fill our space. int childWidthSize = getMeasuredWidth(); int childHeightSize = getMeasuredHeight(); <span style="color: rgb(153, 153, 153); font-family: Monaco, MonacoRegular, 'Courier New', monospace; line-height: 15px; white-space: pre; background-color: rgb(248, 248, 255);"><em>//高度和宽度一样</em></span> heightMeasureSpec = widthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <com.mobisummer.ads.wall.SquareLayout android:id="@+id/layout_icon" android:layout_width="match_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/app_icon" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitXY" > </ImageView> </com.mobisummer.ads.wall.SquareLayout> <TextView android:id="@+id/app_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/layout_icon" android:layout_centerHorizontal="true" > </TextView> </RelativeLayout>
这个效果是不是比之前的好多了? GridView的图片适配差不多了吧。但追求完美的人发现,上面左边的只显示3列,右边的显示4列,如何才能让他们都显示4列呢?
先来说说上面第三步中为什么一个显示3列,而一个则显示4列。
还记得我们在GridView的布局中有:android:columnWidth="100dp"
而左边手机屏幕宽度如果为320dp,320/100 = 3, 则显示3列,而右边手机屏幕宽度为480dp, 480/100 = 4, 当然会显示4列了。
既然,我们设定了GridView列的最小宽度,那么又怎么能改变GridView的列数呢?
细想一下,Androd中是不是有drawable-hdpi / drawable-mdpi这样的文件夹? 还记得的作用和用法吗? 这些不就是用来适配不同手机的图片资源的吗,就是根据手机屏幕不同选择不同的图片资源。
那么,我们当然也可以,根据手机屏幕不同设置不同的GridView列的最小宽度。
如何实现呢? 在项目的res/目录下面添加一个文件夹values-sw480dp, 在res/values-sw480dp/里面添加一个文件dimens.xml。该xml的内容如下:
<?xml version="1.0" encoding="utf-8"?> <resources> <dimen name="gridview_column_width">100dp</dimen> </resources>
<resources> <!-- Default screen margins, per the Android Design guidelines. --> <dimen name="activity_horizontal_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen> <dimen name="gridview_column_width">80dp</dimen> </resources>
<GridView android:id="@+id/gridView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:columnWidth="@dimen/gridview_column_width" android:gravity="center" android:horizontalSpacing="10dp" android:numColumns="auto_fit" android:stretchMode="columnWidth" android:verticalSpacing="10dp" > </GridView>
怎样,GridView的显示风格都差不多了, 美观而统一。
Done~~~
Android中GridView 如何正方形显示图片并适配手机
原文:http://blog.csdn.net/wxx614817/article/details/50977689