一个带时间的相册页面,真小米手机仿小米相册
这个我研究了两天,真要命,昨晚搞出来的。在这里我们用了以下gradle:
compile 'com.android.support:cardview-v7:24.0.0'
compile 'com.android.support:recyclerview-v7:24.2.1'
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.truizlop.sectionedrecyclerview:library:1.0.0'
第一个是卡片,点了有水波效果,
第 2个是你们懂得看名字就知道,
第3个是安卓官方推荐的处理图片的框架,
第4个是一个带头部分组栏的适配器.
首先你们看到的布局,我们来写:
主布局
时间的item:
这个!然后是中间imgview:
cardView可以直接包裹里面的东西,如果里面的东西超过一个的话,包裹一个relativelayout,然后再布局。好,这个imgview是我自己改过的,改成正方形,怎么改掉=的呢?看下面的java继承package com.bbg.textalbum; import android.content.Context; import android.util.AttributeSet; import android.widget.ImageView; /** * Created by administrator on 2017/10/19. */ public class SquareImg extends ImageView { public SquareImg(Context context) { super(context); } public SquareImg(Context context, AttributeSet attrs) { super(context, attrs); } public SquareImg(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public SquareImg(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize(0,widthMeasureSpec),getDefaultSize(0,heightMeasureSpec)); int childwid=getMeasuredWidth(); heightMeasureSpec=widthMeasureSpec=MeasureSpec.makeMeasureSpec(childwid,MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }
那么现在我们要做一个photo的model 就是可以设置属性,路径,然后获取的那种.看看:在这里,其实只要路径和日期就够了,你们注意看了,这个日期是string,不是long。在赋值的时候,将 long的日期变成string.下面会说到package com.bbg.textalbum; /** * Created by administrator on 2017/10/19. */ public class Photo { private String path; private String date; private long id; private String discr; private String name; public Photo(String path, String date, long id, String discr, String name) { this.path = path; this.date = date; this.id = id; this.discr = discr; this.name = name; } public Photo(String path, String date) { this.path = path; this.date = date; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getDiscr() { return discr; } public void setDiscr(String discr) { this.discr = discr; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } }
然后现在我们说一说怎么拿到这些照片,我们是从medisstore拿的,注意要添加权限:三个都加吧在manifest那里加。然后我们在java 用contentResolver获取图片,再获取的时候,我们要分别拿到photo的信息和日期的信息,是两个list.
我们可以在new thread里面获取到两个list,然后传送到handle里面。好的,那现在就已经有数据了,但是适配器呢?看下面,超级麻烦的,我是新手我觉得麻烦咯;package com.bbg.textalbum; import android.content.ContentResolver; import android.database.Cursor; import android.os.Handler; import android.os.Message; import android.provider.MediaStore; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.Toast; import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersDecoration; import com.truizlop.sectionedrecyclerview.SectionedSpanSizeLookup; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; public class MainActivity extends AppCompatActivity { RecyclerView RV; public static List
photos;//这两个是可以在其他java都能访问到的。 public static List photoDates; ContentResolver resolver;//可以通过数据库拿文件的一个工具。 DateFormat format = new SimpleDateFormat("yyyy-MM-dd");//把long转成String RVAdapter adapter;//适配器 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findView(); getPhotos(); } public void findView() { RV = (RecyclerView) findViewById(R.id.RV); resolver = getContentResolver();//要get } Handler handler = new Handler() { @Override public void handleMessage(Message msg) {//先看下面getphoto super.handleMessage(msg); switch (msg.what) { case 1: Bundle bundle = msg.getData();//获取 photos = (ArrayList ) bundle.getParcelableArrayList("photos").get(0);//从msg拿到两个list photoDates = (ArrayList ) bundle.getParcelableArrayList("photos").get(1); adapter = new RVAdapter(photos, photoDates, MainActivity.this); GridLayoutManager manager = new GridLayoutManager(MainActivity.this, 3);//后面数字就是一行几个图片的意思 SectionedSpanSizeLookup lookup = new SectionedSpanSizeLookup(adapter, manager);//这是啥我不知道,关于头部分组的 manager.setSpanSizeLookup(lookup);//设置之后,一个位置占满一行 RV.setLayoutManager(manager);//设RV的布局 RV.setAdapter(adapter); adapter.setOnItemClickListener(new RVAdapter.OnItemClickListener() { @Override public void onItemClick(View view, int position) { Toast.makeText(MainActivity.this,position+": "+photos.get(position).getPath(),Toast.LENGTH_LONG).show(); } }); } } }; public void getPhotos() { new Thread() { @Override public void run() { List list = new ArrayList (); List list1 = new ArrayList ();//记得初始化 super.run(); Cursor cursor = resolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null, MediaStore.Images.Media.DATE_TAKEN + " desc"); if (cursor != null && cursor.moveToFirst()) { do { String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)); long date = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_TAKEN)); long id=cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)); String name=cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME)); String dec=cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME)); Date date1 = new Date(date); String Sdate = format.format(date1);//将long变string Photo photo = new Photo(path, Sdate,id,dec,name);//new一个新photo if (!list1.contains(Sdate)) {//判断日期的list是否已经有了这个照片的日期 list1.add(Sdate);//这个是将日期添加到日期的list } list.add(photo);//这个是照片的list } while (cursor.moveToNext()); cursor.close(); Message msg = new Message(); msg.what = 1;//这个是一个key,就是一个标记吧 Bundle bundle = new Bundle(); ArrayList Alist = new ArrayList();//待会以大的list传送数据 Alist.add(list);//大的list 加入之前的照片list Alist.add(list1);//大的list加入日期的list bundle.putParcelableArrayList("photos", Alist);//bundle加入大的list msg.setData(bundle);//msg设置数据,数据是含有大list的bundle handler.sendMessage(msg);//发送 } } }.start(); } } public class RVAdapter extends SectionedRecyclerViewAdapter
{//remember extends public List photos; Context context; public List photoDates; public static int sectionCount; String[][] path=new String[1000][1000];//这个是我的数组,将list转变为这个数组//我不懂怎么动态初始化//前面的【】是某天,后面【】是某天里面有几张照片 OnItemClickListener onItemClickListener; OnItemLongClickListener onItemLongClickListener; public RVAdapter(List photos, List photoDates,Context context) { this.photos = photos; this.context = context; this.photoDates = photoDates; sectionCount=photoDates.size(); // System.out.println("zhiqian"); // System.out.println(sectionCount); getPath();//其实是将list转变为2D数组 System.out.println(photos.size()+"@@@"+photoDates.size()); } @Override protected MyFootView onCreateSectionFooterViewHolder(ViewGroup parent, int viewType) { return null; }//必须继承 @Override protected MyHeadView onCreateSectionHeaderViewHolder(ViewGroup parent, int viewType) {//必须继承,添加时间item的 View view=LayoutInflater.from(parent.getContext()).inflate(R.layout.headitem,parent,false); return new MyHeadView(view); } @Override protected MyViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {//必须继承,添加主体photo View view=LayoutInflater.from(parent.getContext()).inflate(R.layout.item,parent,false); // System.out.println("photoSize: "+photos.size()+"\n"+"photoDates: "+photoDates.size()); return new MyViewHolder(view); } @Override public void onBindItemViewHolder(MyViewHolder holder, final int section, int position) {//绑定数据,也就是绑定照片 final MyViewHolder viewHolder=(MyViewHolder)holder; // String path=getPath(section)[section][position]; // System.out.println(path); // Ttest(); Glide.with(context).load(new File(path[section][position])).centerCrop().diskCacheStrategy(DiskCacheStrategy.NONE).into(viewHolder.img); //Glide就是加载图片的工具,android官方推荐的 viewHolder.cardView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onItemClickListener.onItemClick(v,viewHolder.getAdapterPosition()-section-1);//-1是因为从0开始的,第一个位置就要变成第0个; } }); } public void setOnItemClickListener(OnItemClickListener itemClick){ this.onItemClickListener=itemClick; } public void setOnItemLongClickListener(OnItemLongClickListener itemLongClick){ this.onItemLongClickListener=itemLongClick; } public interface OnItemClickListener{ void onItemClick(View view,int position); } public interface OnItemLongClickListener{ void onItemLongClick(View view,int position); }//有了这这四个可以有点击的效果 @Override protected void onBindSectionFooterViewHolder(MyFootView holder, int section) { }//必须继承, @Override protected void onBindSectionHeaderViewHolder(MyHeadView holder, int section) { MyHeadView viewHolder=(MyHeadView)holder; viewHolder.dateTV.setText(photoDates.get(section)); }//必须继承,绑定头部时间 @Override protected boolean hasFooterInSection(int section) { return false; }//必须继承,有脚吗? @Override public int getSectionCount() { //return photoDates.size(); // System.out.println(MainActivity.photoDates.size()+""); return MainActivity.photoDates.size(); }//必须继承这个就是一共有多少个日期的。一天就是一个,100天就是一百个 @Override public int getItemCount() { return photos.size()+photoDates.size(); }//必须继承 一个有多少个item,有天数的和照片个数的 @Override protected int getItemCountForSection(int section) { return getCountInsection(section); }//必须继承 public int getCountInsection(int section){ List sectionPhotos=new ArrayList<>(); for (int i=0;i System.out.println(photos.get(0).getPath()); } class MyViewHolder extends RecyclerView.ViewHolder{ CardView cardView; SquareImg img; public MyViewHolder(View itemView) { super(itemView); cardView=(CardView)itemView.findViewById(R.id.cardView); img=(SquareImg)itemView.findViewById(R.id.img); } }//怎么说,这3个就是用到findView的吧 class MyHeadView extends RecyclerView.ViewHolder{ TextView dateTV; public MyHeadView(View itemView) { super(itemView); dateTV=(TextView) itemView.findViewById(R.id.headTV); } } class MyFootView extends RecyclerView.ViewHolder{ public MyFootView(View itemView) { super(itemView); } } }
记得一定要加权限哦读取的权限
http://download.csdn.net/download/x_bx_b/10031735