Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Androi:ListView+GridView實現仿微信微博朋友圈無焦點沖突

Androi:ListView+GridView實現仿微信微博朋友圈無焦點沖突

編輯:關於Android編程

這幾天還是在做那個項目 有一個部分是需要有一個類似微信朋友圈那樣的功能 開始自己實現是用RecycleView嵌套RecycleView 然後已經把別的弄好了 動態圖片那塊還沒有加上結果我不會搞也沒有找到栗子 然後就換了一個思路 看到有listview+gridview的栗子就照著做了一個
先看一下現在的效果
這裡寫圖片描述這裡寫圖片描述vcHLYWZpbmFsv/K83CDgxeDFIM7StPrC68Dvw+bXosrNtcS63M/qz7gg0vLOqmdpdMnPtcTKx7j4ZWNsaXBzZbXEIMv50tTV4rj2ysdqYXKw/LXEwbS90zxhIGhyZWY9"http://download.csdn.net/detail/katherine_qj/9542005">afinal_0.5.1_bin.jar
可以下載復制到AS裡
然後先看一下工程結構
這裡寫圖片描述這裡寫圖片描述

然後 我的順序是先從裡面往外寫 最後寫的MainActivity
不過 就從MainActivity裡面看

package com.example.katherine_qj.listviewgridview;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;

import com.example.katherine_qj.listviewgridviewadapter.GridViewAdapter;
import com.example.katherine_qj.listviewgridviewadapter.ListViewAdapter;
import com.example.katherine_qj.listviewwithgridbean.GridTest;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
 private List listgrid;
    private ListViewAdapter listViewAdapter;
    private ListView listView;
    private String imgs1;
    private  String imgs3;
    private  String imgs2;
    private String imgs4;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listgrid = new ArrayList();
        init();
        initData();
    }
    private void  init(){
    listView = (ListView)findViewById(R.id.listview);

    }
    private void initData(){
        imgs1="http://pic60.nipic.com/file/20150211/18733170_145247158001_2.jpg#"
                +"http://mvimg1.meitudata.com/566507ca1bcc65451.jpg";
        imgs2="http://rj1.douguo.net/upload/diet/6/6/8/666f180617cab130bef1dea9fb3f7fe8.jpg#" +
               "http://img4.duitang.com/uploads/blog/201312/01/20131201120117_F5QXY.jpeg#"+
                "http://www.sh.xinhuanet.com/133071048_13905438457501n.jpg";
        imgs3="http://t2.fansimg.com/uploads2011/02/userid290276time20110205120020.jpg#" +
                "http://image81.360doc.com/DownloadImg/2015/01/2113/49316679_9.jpg#" +
                "http://image.tianjimedia.com/uploadImages/2014/133/11/EN2I6768CHU1_1000x500.jpg#"+
        "http://pic72.nipic.com/file/20150716/6659253_104414205000_2.jpg#"+
                "http://pic36.nipic.com/20131222/10558908_214221305000_2.jpg";
        imgs4 = "http://h.hiphotos.baidu.com/zhidao/pic/item/5243fbf2b21193133f9f1e3967380cd790238d5f.jpg";
        GridTest gridTest = null;
        for(int i = 0;i<=3;i++){
            gridTest = new GridTest();
            switch (i){
                case 0:gridTest.setUsername("小仙女");
                    gridTest.setHeadphoto("http://cdn.duitang.com/uploads/item/201412/12/20141212184514_BJjWy.jpeg");
                    gridTest.setContent("啊啊啊啊啊啊啊萌死了");
                    gridTest.setTime("1分鐘前");
                    gridTest.setImage(imgs1);
                    break;
                case 1:
                    gridTest.setUsername("喵嗚是地球嗎");
                    gridTest.setHeadphoto("http://cdn.duitang.com/uploads/item/201501/19/20150119171935_ZkRsZ.thumb.224_0.jpeg");
                    gridTest.setContent("好吃的日料 超級開心的啦啦啦");
                    gridTest.setTime("3分鐘前");
                    gridTest.setImage(imgs2);
                    break;
                case 2:
                    gridTest.setUsername("ill_kaaa");
                    gridTest.setHeadphoto("http://img5q.duitang.com/uploads/item/201404/03/20140403135406_XFS3M.jpeg");
                    gridTest.setContent("吶吶吶吶吶");
                    gridTest.setTime("5分鐘前");
                    gridTest.setImage(imgs3);
                    break;
                case 3:
                    gridTest.setUsername("Brark");
                    gridTest.setHeadphoto("http://img3.imgtn.bdimg.com/it/u=3367770910,1075442079&fm=21&gp=0.jpg");
                    gridTest.setContent("我又在寫Bug了 難過");
                    gridTest.setTime("5分鐘前");
                    gridTest.setImage(imgs4);
                    break;
            }
            listgrid.add(gridTest);
        }
        listViewAdapter = new ListViewAdapter(this,listgrid);
        listView.setAdapter(listViewAdapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView parent, View view, int position, long id) {
                Toast.makeText(MainActivity.this, "點擊了第" + (position + 1) + "項", Toast.LENGTH_LONG).show();
            }
        });
    }
}

開始聲明了listview的適配器 listview控件
還有四個數據源照片的鏈接 假數據看個樣子
然後oncreat()方法裡 主要有兩個
init()用來找到控件
initData();很明顯就是初始數據的
然後綁定適配器也是在這個裡面完成

嗯 每一個item的子項都是一個類去寫的
GridTest:

package com.example.katherine_qj.listviewwithgridbean;

import java.io.Serializable;

/**
 * Created by Katherine-qj on 2016/6/2.
 */
/*繼承 Serializable 接口之後就可以序列化這個對象方便傳輸數據  很好用*/
public class GridTest implements Serializable{
    private String username;
    private String headphoto;
    private String content;
    private String time;
    private String image;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getHeadphoto() {
        return headphoto;
    }

    public void setHeadphoto(String headphoto) {
        this.headphoto = headphoto;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }
}

SysUtils類

package com.example.katherine_qj.listviewwithgridutil;

import android.app.Activity;
import android.content.Context;
import android.view.Display;
import android.view.WindowManager;

/**
 * Created by Katherine-qj on 2016/6/5.
 */
public class SysUtils {
    public  static int Dp2Px(Context context, float dp){
        final float scale = context.getResources().getDisplayMetrics().density;
       /* android context.getResources().getDisplayMetrics()這是獲取手機屏幕參數,
       後面的density就是屏幕的密度,類似分辨率,但不是
       float scale = getResources().getDisplayMetrics().density;
       density值表示每英寸有多少個顯示點,與分辨率是兩個不同的概念。
       這個得到的不應該叫做密度,應該是密度的一個比例。不是真實的屏幕密度,而是相對於某個值的屏幕密度。
       也可以說是相對密度*/
        return (int) (dp * scale + 0.5f);
    }
    public static int getScreenWidth(Activity activity){
        WindowManager windowManager = activity.getWindowManager();
       /* WindowManager主要用來管理窗口的一些狀態、屬性、view增加、刪除、更新、窗口順序、消息收集和處理等。*/
        Display display = windowManager.getDefaultDisplay();
      /*  獲取默認的顯示對象返回值
        默認的Display對象*/
        return display.getWidth();
    }


}
    /*根據手機的分辨率從 dp 的單位 轉成為 px(像素)

    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

     根據手機的分辨率從 px(像素) 的單位 轉成為 dp

    public static int px2dip(Context context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }*/

重寫的GridView:MyGridView

package com.example.katherine_qj.listviewwithgrid;

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

/**
 * Created by Katherine-qj on 2016/6/2.
 */
public class MyGridView extends GridView {


    public MyGridView(Context context) {

        super(context);
    }

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

    public MyGridView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
   /* AttributeSet 是接收xml中定義的屬性信息
    super後加參數的是用來調用父類中具有相同形式的構造函數
    “this通常指代當前對象,super通常指代父類*/

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE>>2,MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }

   /*
    MeasureSpec.AT_MOST這個是由我們給出的尺寸大小和模式生成一個包含這兩個信息的int變量,這裡這個模式這個參數,傳三個常量中的一個。
    public static int makeMeasureSpec(int size, int mode)
    這個也就是父組件,能夠給出的最大的空間,當前組件的長或寬最大只能為這麼大,當然也可以比這個小。
    onMeasure方法是測量view和它的內容,決定measured width和measured height的,這個方法由 measure(int, int)方法喚起,子類可以覆寫onMeasure來提供更加准確和有效的測量。
    其中兩個輸入參數:
              widthMeasureSpec
      heightMeasureSpec
      分別是parent提出的水平和垂直的空間要求。
              這兩個要求是按照View.MeasureSpec類來進行編碼的。
              參見View.MeasureSpec這個類的說明:這個類包裝了從parent傳遞下來的布局要求,傳遞給這個child。
              每一個MeasureSpec代表了對寬度或者高度的一個要求。
              每一個MeasureSpec有一個尺寸(size)和一個模式(mode)構成。
              MeasureSpecs這個類提供了把一個的元組包裝進一個int型的方法,從而減少對象分配。當然也提供了逆向的解析方法,從int值中解出size和mode*/
}

最重要的兩個適配器:::::
GridViewAdapter:

package com.example.katherine_qj.listviewgridviewadapter;

import android.app.Activity;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ImageView;

import com.example.katherine_qj.listviewgridview.R;
import com.example.katherine_qj.listviewwithgridutil.SysUtils;

import net.tsz.afinal.FinalBitmap;

import java.util.ArrayList;

/**
 * Created by Katherine-qj on 2016/6/2.
 */
public class GridViewAdapter extends BaseAdapter{

    Activity context;
    ArrayList list;
    public Bitmap bitmaps[];
    private FinalBitmap finaImageLoader;
    private int wh;
    public GridViewAdapter(Activity context,ArrayList list){
        this.context = context;
        this.list = list;
        this.wh=(SysUtils.getScreenWidth(context)-SysUtils.Dp2Px(context, 99))/3;
        this.finaImageLoader = FinalBitmap.create(context);/*獲取一個FinalBitmap對象*/
        this.finaImageLoader.configLoadfailImage(R.drawable.loding);/*圖片加載完成前顯示的圖片*/
    }

    @Override
    public int getCount() {

        return list.size();
    }

    @Override
    public Object getItem(int position) {

        return list.get(position);
    }

    @Override
    public long getItemId(int position) {

        return position;
    }

    @Override
    public View getView(int position, View view, ViewGroup parent) {
     Holder holder;//java內部類
        if(view==null){
            view = LayoutInflater.from(context).inflate(R.layout.item_gridview,null);
            holder = new Holder();
            holder.imageView = (ImageView)view.findViewById(R.id.imagevView);
            view.setTag(holder);
            /*首先我們要知道setTag方法是干什麼的,他是給View對象的一個標簽,標簽可以是任何內容,
            我們這裡把他設置成了一個對象,因為我們是把item_gridview.xml的元素抽象出來成為一個類ViewHolder,
            用了setTag,這個標簽就是ViewHolder實例化後對象的一個屬性。我們之後對於ViewHolder實例化的對象holder的操作,
            都會因為Java的引用機制而一直存活並改變convertView的內容,而不是每次都是去new一個。我們就這樣達到的重用*/
        }
        else{
            holder = (Holder)view.getTag();
        }

        finaImageLoader.display(holder.imageView, list.get(position));
        AbsListView.LayoutParams param = new AbsListView.LayoutParams(wh,wh);
       /* 創建一個布局(LayoutParams)的實例 param。
        AbsListView.LayoutParams(wh,wh) 指定了該布局的寬和高;*/
        view.setLayoutParams(param);
        return view;

    }
    class Holder{
        ImageView imageView;
    }

}

ListViewAdapter:

package com.example.katherine_qj.listviewgridviewadapter;

import android.app.Activity;
import android.text.util.Linkify;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.example.katherine_qj.listviewgridview.R;
import com.example.katherine_qj.listviewwithgrid.MyGridView;
import com.example.katherine_qj.listviewwithgridbean.GridTest;
import com.example.katherine_qj.listviewwithgridutil.SysUtils;

import net.tsz.afinal.FinalBitmap;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Katherine-qj on 2016/6/2.
 */
public class ListViewAdapter  extends BaseAdapter{
    private LayoutInflater mInflater;
    private Activity context;
    private List list;
    private FinalBitmap finalBitmap;
    private GridViewAdapter gridViewAdapter;
    private int wh;
    public ListViewAdapter(Activity context, List list){
        super();
        this.mInflater = LayoutInflater.from(context);
        this.context = context;
        this.wh=(SysUtils.getScreenWidth(context)- SysUtils.Dp2Px(context, 99))/3;
        this.list = list;
        this.finalBitmap = FinalBitmap.create(context);
        this.finalBitmap.configLoadfailImage(R.drawable.head);
    }
    public List getlist(){
        return  list;
    }
    @Override
    public int getCount() {

        return list == null ? 0 : list.size();
    }

    @Override
    public Object getItem(int position) {

        return list == null ? null : list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return list == null ? null : position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (list.size()==0){
            return null;
        }
        final ViewHolder holder;
        if(convertView==null){
            convertView = mInflater.inflate(R.layout.item_listview,null);
            holder = new ViewHolder();
            holder.headphoto = (ImageView) convertView.findViewById(R.id.info_iv_head);//頭像
            holder.disName = (TextView) convertView.findViewById(R.id.info_tv_name);//昵稱
            holder.time = (TextView) convertView.findViewById(R.id.info_tv_time);//時間
            holder.content = (TextView) convertView.findViewById(R.id.info_tv_content);//發布內容
            holder.rl4=(RelativeLayout) convertView.findViewById(R.id.rl4);//圖片布局
            holder.gv_images = (MyGridView) convertView.findViewById(R.id.gv_images);//圖片
            convertView.setTag(holder);
        }else {
            holder = (ViewHolder)convertView.getTag();
        }
        final GridTest gridTest = list.get(position);
        String name = null,time = null,content = null,headpath = null,contentimage = null;
        if(gridTest!=null){
            name = gridTest.getUsername();
            time = gridTest.getTime();
            content = gridTest.getContent();
            headpath = gridTest.getHeadphoto();
            contentimage =gridTest.getImage();
        }
        //昵稱
        if (name!=null&&!name.equals("")) {
            holder.disName.setText(name);
        }
        //是否含有圖片
        if (contentimage!=null&&!contentimage.equals("")) {
            holder.rl4.setVisibility(View.VISIBLE);
            initInfoImages(holder.gv_images,contentimage);
        } else {
            holder.rl4.setVisibility(View.GONE);
        }
        //發布時間
        if (time!=null&&!time.equals("")) {
            holder.time.setText(time);
        }
        //內容
        if (content!=null&&!content.equals("")) {
            holder.content.setText(content);
            Linkify.addLinks(holder.content, Linkify.WEB_URLS);
        }
        //頭像
        if (headpath!=null&&!headpath.equals("")) {
            finalBitmap.display(holder.headphoto,headpath);
        } else {
            holder.headphoto.setImageResource(R.drawable.head);
        }
        holder.headphoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                Toast.makeText(context, "點擊了頭像", Toast.LENGTH_LONG).show();
            }
        });

        return convertView;
    }
    static class ViewHolder {
        ImageView headphoto;
        TextView disName;
        TextView time;
        TextView content;
        MyGridView gv_images;
        RelativeLayout rl4;
    }
    public void initInfoImages(MyGridView gv_images,final String imgspath){
        if(imgspath!=null&&!imgspath.equals("")){
            String[] imgs=imgspath.split("#");
            ArrayList list=new ArrayList();
            for(int i=0;i arg0, View arg1,int arg2, long arg3) {
                    Toast.makeText(context, "點擊了第"+(arg2+1)+"張圖片", Toast.LENGTH_LONG).show();
                }
            });
        }

    }

}

上面就是所有的類了 代碼裡面的注釋挺詳細的

還有三個layout;
分別是listview的item
gridview的item
還有activity_main
代碼貼上來吧
activity_main:




    

    
    
    
    
    
    


item_gridview:



    

   

item_listview:



    
    
    
    
        

        

    
    

        
    
    
     

        
        
    


還有一個就是一個selector
list_item_selector:




    
    
    

嗯 所有的有關於實現的都在上面了

其實主要難點就在嵌套的時候gridview的適配器怎麼搞 在那裡加 數據源怎麼傳進去。

這裡的數據源是網絡圖片 所以我們用了一個現成的框架 代碼裡面有注釋 大概oom’之類的問題可以不用考慮
嗯 這裡是把gridview當成子項中的一個部分 所以肯定是要寫在listviewadapter的getview方法裡給它綁定監聽器 大概就這樣
以上over!

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved