刚刚做了一个项目,是做应用墙相关的,就是把一个个应用的图标和名称显示到GridView中。本来想着,像GridView这样常用成熟的控件,使用应该非常的简单,但真正在项目中实现起来,就有各种各样的小问题,其中一个就是不能适配所有的手机型号。
下面就讲解我项目中使用的适配方法,或许不是最好的,如果那位大神有更好的方法,望指点~~
一开始,只是简单的布局GridView,把GridView的列数指定为4列。GridView布局如下:
显示的结果如下:
看上面效果图,在不同分辨率的手机显示,同样是四列,但效果差别非常大。
这是为什么??
这个不难解释,获取的图片资源是一样的, 但手机的分辨率不一样,显示是按图片大小进行自适应的(即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的布局如下:
效果图看出,图片的宽度是合理了,但是高度不合适,高度还是图片实际高度,所以出现拉伸。
回看上面的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();
//高度和宽度一样
heightMeasureSpec = widthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
这个效果是不是比之前的好多了? 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的内容如下:
100dp
16dp
16dp
80dp
怎样,GridView的显示风格都差不多了, 美观而统一。
Done~~~