Android中GridView 如何正方形显示图片并适配手机

       刚刚做了一个项目,是做应用墙相关的,就是把一个个应用的图标和名称显示到GridView中。本来想着,像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>


      而Item的布局也很简单直接:

<?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),所以就出现了上面的现象,那怎么办呢??


二、设定GridView的列宽

       上面是因为图片显示小效果差,那就会想到把ImageView的大小(即GridView列的大小)设置为固定值,然后把图片资源填满,这样不就好OK了么?

        但深究,就会发现,固定大小真的可以吗?比如手机的屏幕大小为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>

       Item的布局如下:

<?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提供的直接的方法,那就只能 自己来了。



三、设置GridView Item的高度

       给控件设定大小,想到的自然是自定义控件里面的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);
    }
}


         
       当然,我其中的需求是图片正方形显示,而不是GridView中的整个Item,因为Item中还包含文本,所以只需要把上面自定义的布局应用于ImageView即可。Item的代码如下:

<?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列呢?



四、GridView适配的优化

       先来说说上面第三步中为什么一个显示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>

         而在res/values/dimens.xml里面也添加这个属性值,只是值的大小不一样,如下:

<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布局里面列的最小宽度columnWidth,不是设置固定大小,而是引用,如下:

    <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~~~



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值