自定义图片选择器

现在的app都需要图片选择器,网上有很多开源的代码,可有时候要根据需求来修改界面,所以要知道图片选择器的原理,图片选择器的实现原理很简单,只要使用ContentResolver这个类就可以了,使用方法有点像数据库通过query函数进行查询,也用到getColumnIndex这个函数,上代码
既然要获取图片,当然要权限
<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"/>
定义图片类Image.java
public class Image {
    private String path;
    private String name;
    private long time;

    public Image(String path,String name,long time){
        this.path = path;
        this.name = name;
        this.time = time;
    }
    public Image(){

    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public long getTime() {
        return time;
    }

    public void setTime(long time) {
        this.time = time;
    }
}
定义文件夹类Folder.java
public class Folder {
    private String name;
    private List<Image> images;


    public Folder(String name,List<Image> images){
        this.name = name;
        this.images = images;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Image> getImages() {
        return images;
    }

    public void setImages(List<Image> images) {
        this.images = images;
    }
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
    private String[] denied;
    private String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            ArrayList<String> list = new ArrayList<>();
            for (int i = 0; i < permissions.length; i++) {
                if (PermissionChecker.checkSelfPermission(this, permissions[i]) == PackageManager.PERMISSION_DENIED) {
                    list.add(permissions[i]);
                }
            }
            if (list.size() != 0) {
                denied = new String[list.size()];
                for (int i = 0; i < list.size(); i++) {
                    denied[i] = list.get(i);
                    ActivityCompat.requestPermissions(this, denied, 5);
                }

            } else {
                init();
            }
        }


    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == 5) {
            boolean isDenied = false;
            for (int i = 0; i < denied.length; i++) {
                String permission = denied[i];
                for (int j = 0; j < permissions.length; j++) {
                    if (permissions[j].equals(permission)) {
                        if (grantResults[j] != PackageManager.PERMISSION_GRANTED) {
                            isDenied = true;
                            break;
                        }
                    }
                }
            }
            if (isDenied) {
                Toast.makeText(this, "请开启权限", Toast.LENGTH_SHORT).show();
            } else {
                init();

            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    private static final String allImage = "全部图片";

    private HashMap<String,Folder> imageFolders = new HashMap<>();
    private List<String> folders = new ArrayList<>();

    private ImageAdapter imageAdapter;


    private ListView listView;


    private Button button;
    private void init(){
        systemImages();

        RecyclerView recyclerView = findViewById(R.id.recycler_view);
        recyclerView.setLayoutManager(new GridLayoutManager(this,4));
        imageAdapter =  new ImageAdapter(this,imageFolders.get(allImage).getImages());
        recyclerView.setAdapter(imageAdapter);


        listView = findViewById(R.id.list_view);
        listView.setAdapter(new ListViewAdapter(this));
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                String key = folders.get(i);
                Folder folder = imageFolders.get(key);
                button.setText(folder.getName());
                imageAdapter.setList(folder.getImages());
                imageAdapter.notifyDataSetChanged();
                listView.setVisibility(View.INVISIBLE);
            }
        });


        button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                listView.setVisibility(View.VISIBLE);
            }
        });
        button.setText(allImage);
    }
    //获取所有图片
    public void systemImages(){
        ContentResolver cr = this.getContentResolver();
        Cursor cursor = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                null, null, null, MediaStore.Images.Media.DEFAULT_SORT_ORDER);
        List<Image> images = new ArrayList<>();
        Folder allImageFolder = new Folder(allImage, images);
        imageFolders.put(allImage,allImageFolder);
        folders.add(allImage);
        if (cursor != null) {
            if (cursor.moveToFirst()) {
                while (!cursor.isAfterLast()) {
                    String fileName = cursor
                            .getString(cursor
                                    .getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME));

                    String path = cursor.getString(cursor
                            .getColumnIndex(MediaStore.Images.Media.DATA));
                    Point point = getSize(path);
                    if(isSize(point.x,point.y)){
                        File file = new File(path);
                        if (accept(file)) {
                            Image image = new Image(path,fileName,file.lastModified());
                            String key = path.substring(0,
                                    path.lastIndexOf(File.separator));
                            List<Image> list;
                            if (imageFolders.containsKey(key)) {
                                list = imageFolders.get(key).getImages();
                            } else {
                                list = new ArrayList<>();
                                Folder folder = new Folder(key.substring(key.lastIndexOf(File.separator) + 1, key.length()), list);
                                imageFolders.put(key, folder);
                                folders.add(key);
                            }
                            list.add(image);
                            images.add(image);
                        }
                    }
                    cursor.moveToNext();
                }
            }
            if (!cursor.isClosed()) {
                cursor.close();
            }
        }
        for (String key : imageFolders.keySet()) {
            List<Image> list = imageFolders.get(key).getImages();
            Collections.sort(list, new FileComparator());
        }
    }
    //判断是否是图片,没想到好的方法,就用文件名来判断
    public boolean accept(File f) {
        String tmp = f.getName().toLowerCase();
        if (tmp.endsWith(".png") || tmp.endsWith(".jpg")
                || tmp.endsWith(".jpeg") || tmp.endsWith(".gif")) {
            return true;
        }
        return false;
    }
    //排序按时间排序
    private class FileComparator implements Comparator<Image> {

        @Override
        public int compare(Image lhs, Image rhs) {
            if (lhs.getTime() < rhs.getTime()) {
                return 1;
            } else if(lhs.getTime() > rhs.getTime()){
                return -1;
            }else{
                return 0;
            }
        }
    }
    //计算图片大小
    private Point getSize(String filePath){
        BitmapFactory.Options bmFactoryOptions = new BitmapFactory.Options();
        bmFactoryOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath,
                bmFactoryOptions);
        return new Point(bmFactoryOptions.outWidth,bmFactoryOptions.outHeight);
    }
    //过滤太小的图片
    private boolean isSize(int width,int height){
        if(height < 200){
            return false;
        }else if(width < 200){
            return false;
        }else if(width*1.0f / height < 0.5){
            return false;
        }else{
            return true;
        }
    }

    //布局
    class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ImageViewHolder>{
        private Context context;
        private List<Image> list;
        public ImageAdapter(Context context,List<Image> list){
            this.context = context;
            this.list = list;
        }

        public void setList(List<Image> list) {
            this.list = list;
        }

        @Override
        public ImageViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
        {
            ImageViewHolder holder = new ImageViewHolder(LayoutInflater.from(context).inflate(R.layout.item_image, parent,
                    false));
            return holder;
        }

        @Override
        public void onBindViewHolder(ImageViewHolder holder, int position) {
            Glide.with(context).asBitmap().load(list.get(position).getPath()).thumbnail(0.1f).into(holder.iv);
        }

        @Override
        public int getItemCount()
        {
            return list.size();
        }

        class ImageViewHolder extends RecyclerView.ViewHolder {

            ImageView iv;

            public ImageViewHolder(View view)
            {
                super(view);
                iv = view.findViewById(R.id.image_view);
            }
        }
    }



    private class ListViewAdapter extends BaseAdapter {
        private LayoutInflater inflater = null;
        private Context context;
        public ListViewAdapter(Context context) {
            this.context = context;
            inflater = LayoutInflater.from(context);
        }


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

        @Override
        public Object getItem(int position) {
            return null;
        }

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            final ViewHolder holder;
            if (convertView == null) {
                convertView = inflater.inflate(R.layout.item_folder, null);
                holder = new ViewHolder();
                holder.textView = convertView.findViewById(R.id.text_view);
                holder.imageView = convertView.findViewById(R.id.image_view);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
            String key = folders.get(position);
            Folder folder = imageFolders.get(key);
            holder.textView.setText(folder.getName());
            Glide.with(context).asBitmap().load(folder.getImages().get(0).getPath()).thumbnail(0.1f).into(holder.imageView);
            return convertView;
        }

        private class ViewHolder {
            TextView textView;
            ImageView imageView;
        }
    }

}
systemImages()函数内就是获取图片路径的方法了
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.selectimage.MainActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">
            <android.support.v7.widget.RecyclerView
                android:id="@+id/recycler_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
            <ListView
                android:id="@+id/list_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="#fff"
                android:visibility="invisible"/>
        </RelativeLayout>
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</android.support.constraint.ConstraintLayout>
item_image.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <com.example.selectimage.SquareImageView
        android:id="@+id/image_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scaleType="centerCrop"
        />
</RelativeLayout>
item_folder.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/text_view"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3"
        />
    <com.example.selectimage.SquareImageView
        android:id="@+id/image_view"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:scaleType="centerCrop"
        />

</LinearLayout>
SquareImageView.java是为了自适应宽度,使图片为正方形
public class SquareImageView extends ImageView {
    public SquareImageView(Context context) {
        super(context);
    }

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if(getMeasuredWidth() != 0){
            setMeasuredDimension(getMeasuredWidth(),getMeasuredWidth());
        }

    }
}
至于Glide可以去网上找教程,很简单的
这只是个简陋的页面,现在可以根据需求来随便更改了


猜你喜欢

转载自blog.csdn.net/u010302327/article/details/79072562