一个带时间的相册页面(仿小米相册)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/x_bx_b/article/details/78294211

一个带时间的相册页面,真小米手机仿小米相册



这个我研究了两天,真要命,昨晚搞出来的。在这里我们用了以下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个是一个带头部分组栏的适配器.

首先你们看到的布局,我们来写:
主布局
 
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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.bbg.textalbum.MainActivity">


<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:id="@+id/RV"
    android:layout_height="match_parent">

</android.support.v7.widget.RecyclerView>
</RelativeLayout>
时间的item:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="wrap_content"
    android:layout_height="wrap_content">
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="10dp"
    android:id="@+id/headTV"
    android:text="159.8.5"
    android:gravity="center"/>
</LinearLayout>
然后是中间imgview:
<?xml version="1.0" encoding="utf-8"?>

<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:id="@+id/cardView"
    android:foregroundTint="@color/cardview_light_background"
    android:layout_height="wrap_content">
<com.bbg.textalbum.SquareImg

    android:id="@+id/img"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
</android.support.v7.widget.CardView>
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 就是可以设置属性,路径,然后获取的那种.看看:
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;
    }
}
在这里,其实只要路径和日期就够了,你们注意看了,这个日期是string,不是long。在赋值的时候,将 long的日期变成string.下面会说到
然后现在我们说一说怎么拿到这些照片,我们是从medisstore拿的,注意要添加权限:
三个都加吧
在manifest那里加。
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
然后我们在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<Photo> photos;//这两个是可以在其他java都能访问到的。
   public static List<String> 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<Photo>) bundle.getParcelableArrayList("photos").get(0);//从msg拿到两个list
                    photoDates = (ArrayList<String>) 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<Photo> list = new ArrayList<Photo>();
                List<String> list1 = new ArrayList<String>();//记得初始化
                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<RVAdapter.MyHeadView,RVAdapter.MyViewHolder,RVAdapter.MyFootView>{//remember extends

    public List<Photo> photos;
    Context context;
    public List<String> photoDates;
    public static int sectionCount;
    String[][] path=new String[1000][1000];//这个是我的数组,将list转变为这个数组//我不懂怎么动态初始化//前面的【】是某天,后面【】是某天里面有几张照片

    OnItemClickListener onItemClickListener;
    OnItemLongClickListener onItemLongClickListener;
    
    public RVAdapter(List<Photo> photos, List<String> 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<Photo> sectionPhotos=new ArrayList<>();
        for (int i=0;i<MainActivity.photos.size();i++){
            if (MainActivity.photoDates.get(section).equals(MainActivity.photos.get(i).getDate())){
                sectionPhotos.add(MainActivity.photos.get(i));
            }
        }
        //这个是获得某一天里面有多少张照片。
        return sectionPhotos.size();
    } 

    public void getPath(){

        int count=0;
        for (×××){
            for (××){
                path[i][j]=photos.get(count).getPath();
                count++;
            }
        }
        //这个是将list转变为2D数据的方法,我自己写的,这4行最烦心,最烧脑。所以我不让你看,想看就下面我的工程呗,AndroidStudio的;
	
        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




            
阅读更多

没有更多推荐了,返回首页