1. 程式人生 > >Android進階:網路與資料儲存—步驟1:Android網路與通訊(第6小節:GridView)

Android進階:網路與資料儲存—步驟1:Android網路與通訊(第6小節:GridView)

內容概要:

  • GirdView(網格檢視)顯示本地資料
  1. GirdView屬性簡介
  2. 案例一:用GirdView展示文字
  3. 案例二:用GridView顯示已安裝應用
  • GridView顯示網路
  1. 用GridView載入網路圖片(上)
  2. 用GridView載入網路圖片(下)

一、GirdView(網格檢視)顯示本地資料

1.GirdView屬性簡介 

在 Android 程式設計中 GridView 跟 ListView 都是比較常用的多控制元件佈局,而 GridView 更是實現九宮圖的首選!

GridView 的用法很多,主要凸顯的是那種網格式布 局,既有橫向也有縱向的資料顯示。

2. GridView 的使用場景

GridView 是 android 開發中常用的一個控制元件,它通常和以下幾塊內容結合使用

  1.  GridView 的九宮格效果

  2.   GridView 的獲取系統應用

  3. GridView 動態載入資料

  4.  擴充套件:GridView 的上拉載入下拉重新整理

3. GridView 中常用的一些屬性 相關屬性解析:

  •  android:numColumns=”auto_fit” //GridView 的列數設定為自動
  •  android:columnWidth=”90dp " //每列的寬度,也就是 Item 的寬度
  •  android:stretchMode=”columnWidth"//縮放與列寬大小同步(每列單元格的寬度自適應,邊距固定)
  •  android:stretchMode=”SpacingWidth"//(每列單元格的寬度固定,邊距自適應)
  •  android:verticalSpacing=”10dp” //兩行之間的邊距
  • android:horizontalSpacing=”10dp” //兩列之間的邊距
  •  android:cacheColorHint="#00000000" //去除拖動時預設的黑色背景
  •  android:listSelector="#00000000" //去除選中時的黃色底色
  •  android:scrollbars="none" //隱藏 GridView 的滾動條
  •  android:fadeScrollbars="true" //設定為 true 就可以實現滾動條的自動隱藏和顯示
  • android:fastScrollEnabled="true" //GridView 出現快速滾動的按鈕(至少滾動4 頁才會顯示)
  • android:fadingEdge="none" //GridView 衰落(褪去)邊緣顏色為空,預設值是vertical。(可以理解為上下邊緣的提示色)
  • android:fadingEdgeLength="10dip" //定義的衰落(褪去)邊緣的長度
  • android:stackFromBottom="true" //設定為 true 時,你做好的列表就會顯示你列表的最下面
  • android:transcriptMode="alwaysScroll" //當你動態新增資料時,列表將自動 往下滾動最新的條目可以自動滾動到可視範圍內
  • android:drawSelectorOnTop="false"//點選某條記錄不放,顏色會在記錄的後 面成為背景色,內容的文字可見(預設為 false)

4.GridView 實現資料載入的步驟:

GridView 適合“網格式佈局”的開發模式,即從每個條目的顯示元件,到對其進行控 制的資料結構,最後通過 Activity 等進行使用。

  • 1)  首先是 item 元件,即用於每項佈局輸出的 xml 檔案。
  • 2)  在 Activity 的佈局中載入《GridView》控制元件,並設定一系列屬性
  • 3)  定義資料結構(容器),即用於持有單個 Item 的資料,可以是簡單的 String,也可
  • 以通過抽象 Items 所需欄位組成一個類,抽象的原則是與 Item 中的元件對應。本
  • 文中上圖涉及多個欄位,因此通過抽象元件形成 BBSTopicItem 類。
  • 4)  列表介面卡。決定每行 Item 中具體顯示什麼內容,以怎樣的樣式顯示等,通常通過繼承 ArrayAdapter、SimpleAdapter 等實現。本文定義 BaseAdapter
  • 5)  定義資料來源,並對資料來源進行初始化
  • 6) 將介面卡設定給 GridView

二、案例

1.案例一:用GirdView展示文字

佈局檔案

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

  <GridView
      android:id="@+id/girdview"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:numColumns="3"
      android:columnWidth="90dp"
      android:stretchMode="columnWidth"
      android:verticalSpacing="10dp"
      android:horizontalSpacing="10dp"
      android:gravity="center"

      >

  </GridView>
</LinearLayout>

每一個格子item佈局

<?xml version="1.0" encoding="utf-8"?>
<!--必須以TextView開頭-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:id="@+id/textView"
    android:layout_height="wrap_content"
    android:textStyle="bold"
    android:textColor="#000000"
    android:textSize="40sp"
    android:text="text"
    android:background="#ed2f52"
    >
</TextView>

 和ListView使用一樣,只是樣式不同


public class GridView_Text extends AppCompatActivity {
    GridView girdView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.girdview_text);
        girdView=findViewById(R.id.girdview);
        //設定固定資料
        List<String> datalist=new ArrayList<>();
        for (int i = 0; i <9 ; i++) {
            datalist.add("單元格"+(i+1));
        }
        //設定簡單的陣列介面卡
        ArrayAdapter<String> arrayAdapter=new ArrayAdapter<>(this,R.layout.item_view,datalist);
        girdView.setAdapter(arrayAdapter);

    }
}

2.案例二:用GridView顯示已安裝應用

獲取系統已經安裝的應用的方法:getAppInfo() 

在方法里加上下面這句可以過濾掉系統自帶應用

    //過濾掉系統應用
      if((packageInfo.applicationInfo.flags& ApplicationInfo.FLAG_SYSTEM)==0)

主介面GridView_app.java

public class GridView_app extends AppCompatActivity {

    private GridView gridView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.gridview_app);
        gridView = findViewById(R.id.girdview);
        gridView.setAdapter(new GridAdapter_app(this, getAppInfo()));
    }

    //獲取系統應用app資訊
    public List<AppInfo> getAppInfo() {
        List<AppInfo> AppInfolist = new ArrayList<>();
        //使用包管理器
        PackageManager packageManager = getPackageManager();
        //返回一個包的資訊PackageInfo
        List<PackageInfo> installedPackages = packageManager.getInstalledPackages(0);
        for (int i = 0; i < installedPackages.size(); i++) {
            //拿到包裡面的資訊
            PackageInfo packageInfo = installedPackages.get(i);
            AppInfo appInfo = new AppInfo();
            //獲取包裡面應用名給appInfo裡的應用名稱賦值
            appInfo.setAppName(packageInfo.applicationInfo.loadLabel(packageManager).toString());
            appInfo.setAppIcon(packageInfo.applicationInfo.loadIcon(packageManager));
            appInfo.setVersionCode(packageInfo.versionCode);
            appInfo.setVersionName(packageInfo.versionName);
            appInfo.setPackageName(packageInfo.packageName);
            AppInfolist.add(appInfo);
            //過濾掉系統應用
//            if((packageInfo.applicationInfo.flags& ApplicationInfo.FLAG_SYSTEM)==0)
            AppInfolist.add(appInfo);

        }
        return AppInfolist;

    }
}

封裝應用資訊的實體類 AppInfo

/***
 * 建一個實體類封裝應用資訊
 */
public class AppInfo {
    //應用名稱
    private String appName;
    //應用包名
    private String packageName;
    //版本名稱
    private String versionName;
    //版本號
    private int versionCode;
    //應用圖示
    private Drawable appIcon;

    public String getAppName() {
        return appName;
    }

    public void setAppName(String appName) {
        this.appName = appName;
    }

    public String getPackageName() {
        return packageName;
    }

    public void setPackageName(String packageName) {
        this.packageName = packageName;
    }

    public String getVersionName() {
        return versionName;
    }

    public void setVersionName(String versionName) {
        this.versionName = versionName;
    }

    public int getVersionCode() {
        return versionCode;
    }

    public void setVersionCode(int versionCode) {
        this.versionCode = versionCode;
    }

    public Drawable getAppIcon() {
        return appIcon;
    }

    public void setAppIcon(Drawable appIcon) {
        this.appIcon = appIcon;
    }
}

 設定資料介面卡

public class GridAdapter_app extends BaseAdapter {
    private Context context;
    private List<AppInfo> appInfoList;
    private ViewHolder viewHolder;

    //建構函式 將資料傳進來
    public GridAdapter_app(Context context, List<AppInfo> appInfoList) {
        this.context = context;
        this.appInfoList = appInfoList;
    }

    @Override
    public int getCount() {
        return appInfoList.size();
    }

    @Override
    public Object getItem(int position) {
        return appInfoList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        //優化GridView
        if (convertView == null) {
             viewHolder = new ViewHolder();
            //convertView=View.inflate(context,R.layout.gridview_app,null);
            //繫結item佈局.上下兩種方法都可以
            convertView = LayoutInflater.from(context).inflate(R.layout.item_app_view, null);
            viewHolder.iv_aapIcon = convertView.findViewById(R.id.app_icon);
            viewHolder.tv_appName = convertView.findViewById(R.id.app_name);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        //設定資料
        AppInfo appInfo = appInfoList.get(position);
        viewHolder.tv_appName.setText(appInfo.getAppName() + " " + appInfo.getVersionName());
        viewHolder.iv_aapIcon.setImageDrawable(appInfo.getAppIcon());
        return convertView;
    }

    public class ViewHolder {
        TextView tv_appName;
        ImageView iv_aapIcon;
    }
}

在初始化時新增介面卡

       //傳參設定介面卡
        gridView.setAdapter(new GridAdapter_app(this, getAppInfo()));

3.案例三:用GridView載入網路圖片(上)

1.設定佈局

2.設定介面卡

3.獲取資料,從網路上下載圖片

  1. 網路連線下載(記得新增網路許可權在AndroidMainfest.xml中)
  2. 放到非同步任務AsyncyTask中執行下載操作
  3. 下載完成提示更新UI

介面卡設定

public class GridAdapter_internet extends BaseAdapter {
    private List<ImageInfo> imageInfoList;
    private Context context;
    private ViewHolder viewHolder;

    public GridAdapter_internet(Context context, List<ImageInfo> imageInfos) {
        this.context = context;
        this.imageInfoList = imageInfos;
    }

    @Override
    public int getCount() {
        return imageInfoList.size();
    }

    @Override
    public Object getItem(int position) {
        return imageInfoList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        //優化效能
        if (convertView == null) {
            viewHolder = new ViewHolder();
            convertView = View.inflate(context, R.layout.item_internet_view, null);
            viewHolder.text = convertView.findViewById(R.id.app_name);
            viewHolder.imageView = convertView.findViewById(R.id.app_icon);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        ImageInfo imageInfo = imageInfoList.get(position);
        viewHolder.text.setText(imageInfo.getText());
        if (imageInfo.getBitmap() == null)//如果圖片還沒載入來
        {//就預設給它載入一張本地圖
            viewHolder.imageView.setImageResource(R.mipmap.ic_launcher);
        } else
            viewHolder.imageView.setImageBitmap(imageInfo.getBitmap());
        return convertView;
    }

    public class ViewHolder {
        public TextView text;
        public ImageView imageView;
    }
}

圖片資訊:

public class ImageInfo {
    private String imagePath;
    private Bitmap  bitmap;
    private String text;

    public String getImagePath() {
        return imagePath;
    }

    public void setImagePath(String imagePath) {
        this.imagePath = imagePath;
    }

    public Bitmap getBitmap() {
        return bitmap;
    }

    public void setBitmap(Bitmap bitmap) {
        this.bitmap = bitmap;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}

主Activity

public class GridView_internet extends AppCompatActivity {
    private List<String> imgList;
    private List<ImageInfo> imageInfoList;
    private GridAdapter_internet gridAdapter_internet;
    private GridView gridView;
    private ImageLoadTask imageLoadTask;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.gridview_internet);
        gridView = findViewById(R.id.girdview);
        initData();
    }

    private void initData() {
        imgList = new ArrayList<>();
        imgList.add("http://img5.duitang.com/uploads/item/201406/26/20140626164837_dzKds.jpeg");
        imgList.add("http://img2.imgtn.bdimg.com/it/u=3980629563,3881837630&fm=21&gp=0.jpg");
        imgList.add("http://img5q.duitang.com/uploads/item/201505/08/20150508155052_XJaNW.jpeg");
        imgList.add("http://img4.duitang.com/uploads/item/201407/02/20140702105736_FdN5P.jpeg");
        imgList.add("http://img2.imgtn.bdimg.com/it/u=2866652161,3841912673&fm=21&gp=0.jpg");
        imgList.add("http://img4.imgtn.bdimg.com/it/u=883757693,2063816225&fm=21&gp=0.jpg");
        imgList.add("http://cdn.duitang.com/uploads/item/201309/26/20130926110955_QtUdX.jpeg");
        imgList.add("http://zjimg.5054399.com/allimg/160815/14_160815161625_9.jpg");
        imgList.add("http://i-7.vcimg.com/trim/09ce7067d2467c54cf05bbd271ee3ec8430415/trim.jpg");
        imageInfoList = new ArrayList<ImageInfo>();
        for (int i = 0; i < imgList.size(); i++) {
            ImageInfo imageInfo = new ImageInfo();
            imageInfo.setImagePath(imgList.get(i));
            imageInfo.setText("圖片" + (i + 1));
            imageInfoList.add(imageInfo);
        }
        //設定介面卡
        gridAdapter_internet = new GridAdapter_internet(this, imageInfoList);
        gridView.setAdapter(gridAdapter_internet);
        //非同步下載
        imageLoadTask = new ImageLoadTask(this, gridAdapter_internet);
        imageLoadTask.execute();
    }

    //在網路上下載圖片返回Bitmap
    public Bitmap getImagefornet(String path) {
        try {
            URL url = new URL(path);
            //發起連結
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            httpURLConnection.setDoInput(true);
            httpURLConnection.setConnectTimeout(10000);//超時時間
            httpURLConnection.connect();
            //拿到的輸入流讀取
            InputStream inputStream = httpURLConnection.getInputStream();
            //轉換成Bitmap
            Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
            inputStream.close();
            return bitmap;

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    //非同步任務下載操作
    public class ImageLoadTask extends AsyncTask<String, Void, Void> {
        Context context;
        GridAdapter_internet gridAdapter_internet;

        private ImageLoadTask(Context context, GridAdapter_internet gridAdapter_internet) {
            this.gridAdapter_internet = gridAdapter_internet;
        }

        @Override
        protected Void doInBackground(String... strings) {
            for (int i = 0; i < gridAdapter_internet.getCount(); i++) {
                //拿到圖片物件
                ImageInfo imageInfo = (ImageInfo) gridAdapter_internet.getItem(i);
                Bitmap bitmap = getImagefornet(imageInfo.getImagePath());//呼叫下載圖片的方法
                imageInfo.setBitmap(bitmap);//將下載的圖片放到控制元件上
                publishProgress();//通知重新整理UI
            }
            return null;
        }
        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            gridAdapter_internet.notifyDataSetChanged();
        }
    }


}

效果: 

使用Google的的網路庫Glide去載入圖片

在build.gradle中dependencies

新增依賴包 

    implementation 'com.github.bumptech.glide:glide:3.7.0'

在Adapter中getView中新增,直接下載好圖片

    //with第一個引數上下文
        // load第二個圖片地址、
        //placeholder第三個佔位符(預設圖片)
        // centerCrop居中裁切顯示
        // 預設緩衝
        //into到你要顯示的元件上
        Glide.with(context).load(imageInfo.getImagePath()).
                placeholder(R.mipmap.ic_launcher).centerCrop().
                into(viewHolder.imageView);
//        if (imageInfo.getBitmap() == null)//如果圖片還沒載入來
//        {//就預設給它載入一張本地圖
//            viewHolder.imageView.setImageResource(R.mipmap.ic_launcher);
//        } else
//            viewHolder.imageView.setImageBitmap(imageInfo.getBitmap());

然後主Activity中的AsyncTask都可以省略了(取代了AsyncTask的下載操作)

    //設定介面卡
        gridAdapter_internet = new GridAdapter_internet(this, imageInfoList);
        gridView.setAdapter(gridAdapter_internet);

速度更快,不用每次都重新下載,會自動快取下來,所以下次開啟就很快就有圖片了