編輯:關於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!
原因一:Activity的啟動模式那麼Activity以哪種啟動模式進行跳轉時,會導致目標Activity獲取不到傳遞過來的數據呢?在上一篇博客中講到Activity以不
本文要講自己定義一個標題欄,能加事件。然後可以移值到不同的手機上,基本上不用改什麼,調用也很簡單在layout文件夾下,新建一個XML。名字叫做layout_title_
目前,各種App的社區或者用戶曬照片、發說說的地方,都提供了評論功能,為了更好地學習,自己把這個功能實現了一下,做了個小的Demo。首先推薦一款實用的插件LayoutCr
打開/dev/graphics/fb0節點的過程:打開/dev/graphics/fb0這個設備的調用過程如下:1.在HWComposer中,加載moduleHWComp