Android基础控件—GridView

本文介绍了Android中的GridView,一种用于显示多内容的网格视图,常用于菜单和照片墙效果。讲解了如何通过代码实现GridView,展示了一个照片墙的效果,并详细说明了GridView的重要属性,如列数、宽度、间距等。同时,讨论了在子线程中处理大量图片以避免ANR问题及使用Handler在主线程中更新UI的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.GridView是什么?

       GridView又称为网格视图或者九宫格视图,当手机屏幕上需要显示比较多的内容时(包括文字、图片或者其它元素),可以使用GridView。最常见的GridView使用在于早期Android手机的一二级菜单和相册里的照片墙效果,当然如果将GridView的这种布局方式用于软件的主页面用来显示菜单,也是比较好的选择。

2.代码中具体实现

       接下来就使用GridView实现照片墙的效果来简单的介绍一下GridView的用法。

       实现后的效果:

       

       下面是一些GridView属性:

  • android:numColumns="auto_fit" ,GridView的列数设置为自动
  • android:columnWidth="90dp",每列的宽度,也就是Item的宽度
  • android:stretchMode="columnWidth",缩放与列宽大小同步
  • android:verticalSpacing="10dp",两行之间的边距,如:行一(NO.0~NO.2)与行二(NO.3~NO.5)间距为10dp
  • android:horizontalSpacing="10dp",两列之间的边距
     首先我们要先准备好GridView所需要的布局文件以及item的布局文件
//GridView的布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.chupeng.gridviewdemo.MainActivity">

    <GridView
        android:id="@+id/gridView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:horizontalSpacing="5dp"
        android:verticalSpacing="5dp"
        android:numColumns="3"
        android:listSelector="@android:color/transparent"
        android:stretchMode="columnWidth">

    </GridView>
</LinearLayout>

//GridView的item的布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center">

    <com.example.chupeng.gridviewdemo.SquareImageView
        android:id="@+id/squareImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/gray"
        android:layout_margin="5dp"
        android:scaleType="centerCrop"/>

</LinearLayout>
       仔细看GridView的item的布局文件可以注意到,这里并没有采用ImageView而是用的是一个叫SquareImageView的自定义View,顾名思义这里就是为了GridView的每个item都是正方形,这样整个照片墙看起来比较整齐美观。需要实现一个正方形的ImageView非常简单,只需要在它的onMeasure方法中将宽和高设置成一样的就好。

package com.example.chupeng.gridviewdemo;

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

/**
 * Created by ChuPeng on 2017/2/25.
 */

public class SquareImageView extends ImageView
{

    public SquareImageView(Context context)
    {
        super(context);
    }

    public SquareImageView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    public SquareImageView(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
    }

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        //将宽和高设置为一样的
        super.onMeasure(widthMeasureSpec, widthMeasureSpec);
    }
}
       可以看到,我们在SquareImageView的onMeasure()方法中巧妙的将heightMeasureSpec替换为widthMeasureSpec,这样就可以得到一个正方形的ImageView了,这里涉及到了View的工作流程相关的知识。接这需要实现一个GridView的适配器,这里的实现方式跟ListView非常相似。

package com.example.chupeng.gridviewdemo;

import android.content.Context;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import java.util.List;

/**
 * Created by ChuPeng on 2017/2/25.
 */

public class ImageAdapter extends BaseAdapter
{
    private Context context;
    private List<Bitmap> list;

    public ImageAdapter(Context context, List<Bitmap> list)
    {
        this.context = context;
        this.list = list;
    }

    public int getCount()
    {
        return list.size();
    }

    public Object getItem(int position)
    {
        return list.get(position);
    }

    public long getItemId(int position)
    {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup viewGroup)
    {
        Bitmap bitmap = list.get(position);
        View view;
        ViewHolder viewHolder;
        if(convertView == null)
        {
            view = LayoutInflater.from(context).inflate(R.layout.gridview_item, null);
            viewHolder = new ViewHolder();
            viewHolder.squareImage = (SquareImageView) view.findViewById(R.id.squareImage);
            //将ViewHolder存储在view中
            view.setTag(viewHolder);
        }
        else
        {
            view = convertView;
            viewHolder = (ViewHolder) view.getTag();
        }
        viewHolder.squareImage.setImageBitmap(bitmap);
        return view;
    }

    class ViewHolder
    {
        SquareImageView squareImage;
    }
}
       紧接着将ImageAdapter设置给GridView,这样一个绚丽大方的图片墙就大功告成了

package com.example.chupeng.gridviewdemo;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.GridView;
import java.util.ArrayList;
import java.util.List;


public class MainActivity extends AppCompatActivity
{
    private List<Bitmap> list;
    private Bitmap bitmap;
    private GridView gridView;
    private ImageAdapter adapter;
    private Handler handler;

    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        gridView = (GridView) findViewById(R.id.gridView);

        handler = new Handler()
        {
            public void handleMessage(Message msg)
            {
                switch (msg.what)
                {
                    case 123:
                        adapter = new ImageAdapter(MainActivity.this, (List<Bitmap>) msg.obj);
                        gridView.setAdapter(adapter);//将ImageAdapter设置给GridView
                        break;
                }
            }
        };

        gridView.setOnItemClickListener(new AdapterView.OnItemClickListener()
        {
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                Intent intent = new Intent(MainActivity.this, ShowActivity.class);
                Bundle bundle = new Bundle();
                bundle.putParcelable("data", list.get(position));
                intent.putExtras(bundle);
                startActivity(intent);
            }
        });

        new Thread(new Runnable()
        {
            public void run()
            {
                list = new ArrayList<Bitmap>();//给list中添加图片
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.beer);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.bread);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.breakfast);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.burger);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.cake);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.carrot);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.check);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.chicken);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.closed);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.cocktails);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.coffeecup);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.croissant);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.cutlery1);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.cutlery);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.favorite);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.fish);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.fork);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.fruits);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.icecream);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.invoice);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.juice);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.kettle1);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.kettle);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.lobster);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.menu);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.mushrooms);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.napkins);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.open);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.pan);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.paymentmethod);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.pieceofcake);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.pizza);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.reserved);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.restaurant);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.saltandpepper);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.sausage);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.skewer);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.soup);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.spoon);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.steak);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.sushi);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.sushi1);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.sushi);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.table);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.teacup);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.terrace);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.tray1);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.tray);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.vegetables);
                list.add(bitmap);
                bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.wine);
                list.add(bitmap);
                Message message = new Message();
                message.what = 123;
                message.obj = list;
                handler.sendMessage(message);
            }
        }).start();
    }
}
3.总结

       在MainActivity中将给list中添加图片的功能放到子线程中去操作,这样主要是为了防止图片数量过多造成ANR(主线程进行耗时操作,造成主线程阻塞),可是当在子线程中完成添加图片的操作以后我们不能直接在子线程中完成ImageAdapter的初始化和给GridView设置adapter,因为在ImageAdapter的初始化的过程中需要给SquareImageView
添加图片,这里的过程就属于改变UI的操作,而Android系统不允许在子线程中对UI进行改变,因为在子线程中改变UI是不安全的,所以我们这里还需要利用Handler机制将list传入到主线程中,才能完成接下来的操作,否则将会抛出异常。




       以上Demo的源代码地址:点击打开链接






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值