Android自定义View之相册文件选择器

一、导入依赖

api 'com.github.LuckSiege.PictureSelector:picture_library:v2.3.6'

二、自定义FilePicker类,相册选择器

package com.custom.jfrb.util; //自己的包名位置

import android.app.Activity;
import androidx.fragment.app.Fragment;

import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.config.PictureMimeType;

public class FilePicker {
    public static final int FROM_ALBUM = 20001;
    public static final int TAKE_PICTURE = 20005;

    int selectionMode = PictureConfig.MULTIPLE;
    int mimeType = PictureMimeType.ofAll();
    int maxChoose = 20;
    boolean previewImage = true;
    boolean isCrop = false;
    boolean isCircleCrop = true;
    public boolean isShowCamera = false;
    int cropWidth;
    int cropHeight;
    Activity activity;

    Fragment fragment;

    public FilePicker(Activity activity) {
        this.activity = activity;
    }

    public FilePicker(Fragment fragment) {
        this.fragment = fragment;
    }

    public void start() {
        PictureSelector pictureSelector;
        if (activity != null) {
            pictureSelector = PictureSelector.create(activity);
        } else {
            pictureSelector = PictureSelector.create(fragment);
        }
        pictureSelector.openGallery(mimeType)//全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()
                .loadImageEngine(GlideEngine.createGlideEngine())
                .maxSelectNum(maxChoose)// 最大图片选择数量 int
                .minSelectNum(1)// 最小选择数量 int
                .imageSpanCount(4)// 每行显示个数 int
                .selectionMode(selectionMode)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
                .previewImage(previewImage)// 是否可预览图片 true or false
                .previewVideo(false)// 是否可预览视频 true or false
                .enablePreviewAudio(false) // 是否可播放音频 true or false
                .isCamera(isShowCamera)// 是否显示拍照按钮 true or false
                .isZoomAnim(false)// 图片列表点击 缩放效果 默认true
                .sizeMultiplier(0.5f)// glide 加载图片大小 0~1之间 如设置 .glideOverride()无效
                .enableCrop(isCrop)// 是否裁剪 true or false
                .withAspectRatio(cropWidth, cropHeight)
                .circleDimmedLayer(isCircleCrop)
                .scaleEnabled(true)
                .rotateEnabled(false) // 裁剪是否可旋转图片
                .compress(true)// 是否压缩 true or false
                .cropCompressQuality(80)
                .isGif(false)// 是否显示gif图片 true or false
                .openClickSound(false)// 是否开启点击声音 true or false
                .forResult(FROM_ALBUM);//结果回调onActivityResult code

    }

    public void start(int requestId) {
        PictureSelector pictureSelector;
        if (activity != null) {
            pictureSelector = PictureSelector.create(activity);
        } else {
            pictureSelector = PictureSelector.create(fragment);
        }
        pictureSelector.openGallery(mimeType)//全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()
                .maxSelectNum(20)// 最大图片选择数量 int
                .minSelectNum(1)// 最小选择数量 int
                .imageSpanCount(4)// 每行显示个数 int
                .selectionMode(selectionMode)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
                .previewImage(false)// 是否可预览图片 true or false
                .previewVideo(false)// 是否可预览视频 true or false
                .enablePreviewAudio(false) // 是否可播放音频 true or false
                .isCamera(false)// 是否显示拍照按钮 true or false
                .isZoomAnim(false)// 图片列表点击 缩放效果 默认true
                .sizeMultiplier(0.5f)// glide 加载图片大小 0~1之间 如设置 .glideOverride()无效
                .enableCrop(isCrop)// 是否裁剪 true or false
                .circleDimmedLayer(true)
                .hideBottomControls(true)
                .rotateEnabled(true) // 裁剪是否可旋转图片
                .compress(false)// 是否压缩 true or false
                .hideBottomControls(true)// 是否显示uCrop工具栏,默认不显示 true or false
                .isGif(false)// 是否显示gif图片 true or false
                .openClickSound(false)// 是否开启点击声音 true or false
                .forResult(requestId);//结果回调onActivityResult code
    }

    // 开启拍照
    public void startPicture() {
        PictureSelector pictureSelector;
        if (activity != null) {
            pictureSelector = PictureSelector.create(activity);
        } else {
            pictureSelector = PictureSelector.create(fragment);
        }

        pictureSelector
                .openCamera(PictureMimeType.ofImage())
                .enableCrop(isCrop)// 是否裁剪 true or false
                .circleDimmedLayer(isCrop)
                .rotateEnabled(true) // 裁剪是否可旋转图片
                .forResult(TAKE_PICTURE);
    }

    public void setSelectionMode(int selectionMode) {
        this.selectionMode = selectionMode;
    }

    public void setMimeType(int mimeType) {
        this.mimeType = mimeType;
    }

    public void setMaxChoose(int maxChoose) {
        this.maxChoose = maxChoose;
    }

    public void setCrop(boolean isCrop) {
        this.isCrop = isCrop;
    }

    public void setCircleCrop(boolean isCircleCrop) {
        this.isCircleCrop = isCircleCrop;
    }

    public void setCropWidth(int cropWidth) {
        this.cropWidth = cropWidth;
    }

    public void setCropHeight(int cropHeight) {
        this.cropHeight = cropHeight;
    }

    public void setPreviewImage(boolean previewImage) {
        this.previewImage = previewImage;
    }
}

三、场景使用1(选择单个图片作为头像/封面等)

效果:

相册选择器选择单个图片

1、给某个控件添加监听,调用相册文件选择器

//选择相册文件后显示在ivUpload控件上
ImageView ivUpload = findViewById(R.id.img_upload)
FilePicker filePicker = new FilePicker(this);
filePicker.setMimeType(PictureMimeType.ofImage()); //选择类型是图片,只调出相册中所有图片文件
filePicker.setMaxChoose(1); //单次最多选择文件数量为1,可变
filePicker.setCrop(true);
filePicker.isShowCamera = true; //设置打开后有开始拍照项
filePicker.setCircleCrop(false);
filePicker.setCropWidth(ivUpload.getWidth()); 
filePicker.setCropHeight(ivUpload.getHeight());
filePicker.start();

2、选择图片后回调

    @SuppressLint("MissingSuperCall")
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == FROM_ALBUM) {
            if (resultCode == Activity.RESULT_OK) {
                String path;
                List<LocalMedia> selectList = PictureSelector.obtainMultipleResult(data);
                if (selectList != null && !selectList.isEmpty()) {
                    if (selectList.get(0).isCut()) {
                        path = selectList.get(0).getCutPath();
                    } else if (selectList.get(0).isCompressed()) {
                        path = selectList.get(0).getCompressPath();
                    } else {
                        path = selectList.get(0).getPath();
                    }   
                    //加载选择的图片到控件中
                    Glide.with(context).load(path).apply(options).into(ivUpload);
                }
            }
        }
    }

四、场景使用2(选择多个视频 /(图片)展示到页面上)

效果:

相册选择器选择多个视频

1、给某个控件添加监听,调用相册文件选择器

FilePicker filePicker = new FilePicker(this);
filePicker.setMimeType(PictureMimeType.ofVideo()); //设置选择类型为视频
filePicker.setMaxChoose(30); //设置单次选择最大数量为30个
filePicker.setSelectionMode(PictureConfig.MULTIPLE);
filePicker.start();

2、选择视频回调

    @SuppressLint("MissingSuperCall")
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case FROM_ALBUM:
                //选择相册文件后回调
                if (resultCode == Activity.RESULT_OK) {
                    List<LocalMedia> selectList = PictureSelector.obtainMultipleResult(data);
                    if (selectList != null && selectList.size() > 0){
                        int testCount = 0;
                        String productPath = null;
                        for (LocalMedia localMedia : selectList) {
                            String path = localMedia.getPath();
                            String TAG = "mylog_upload_file";
                            Log.i(TAG, "压缩::" + localMedia.getCompressPath());
                            Log.i(TAG, "原图::" + localMedia.getPath());
                            Log.i(TAG, "裁剪::" + localMedia.getCutPath());
                            Log.i(TAG, "是否开启原图::" + localMedia.isOriginal());
                            Log.i(TAG, "原图路径::" + localMedia.getOriginalPath());
                            Log.i(TAG, "Android Q 特有Path::" + localMedia.getAndroidQToPath());
                            if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.Q) {
                                // 这个设备的 Android 版本大于 Android Q
                                // 在这里执行你的代码
                                path = localMedia.getAndroidQToPath();
                            } else if(localMedia.isOriginal()){
                                Log.i(TAG, "原图路径::" + localMedia.getOriginalPath());
                                path = localMedia.getOriginalPath();
                            }else{
                                path = localMedia.getCompressPath();
                            }
                            Log.d("mylog_upload_file","选择文件的路径是:"+ path);
                            FileInfoStatus fileInfo = null;
                                if(PublicUtils.isVideo(path)){
                                    fileInfo = getLocalFile(path);  //根据路径信息创建自己的JavaBean对象进行信息的展示,也可以创建List对象去存储,进而可以展示到recyclerview或其他布局中
                                }else{
                                    RnToast.showToastLong(this,"只支持Mp3文件!");
                                }
                        }
                    }
                }
                break;
            default:
                break;
        }
    }

FileInfoStatus为自己定义的文件信息类

package com.custom.jfrb.ui.fileTransfer.FileUploadUtils.bean;

import android.graphics.BitmapFactory;

import com.custom.jfrb.ui.fileTransfer.FileUploadUtils.base.DataTypeEnum;
import com.custom.jfrb.ui.fileTransfer.FileUploadUtils.db.DBHelper;
import com.custom.jfrb.ui.first.bean.MaterialDTO;
import com.custom.jfrb.util.PublicUtils;
import com.qukan.qkrecordupload.ConfigureManagerUtil;
import com.qukan.qkrecordupload.QkApplication;

import java.io.File;
import java.io.Serializable;

import static com.custom.jfrb.ui.fileTransfer.FileUploadUtils.base.DataTypeEnum.DISK;


public class FileInfoStatus extends com.qukan.qkrecordupload.file.FileInfoStatus implements Serializable {

    public static final double GB = 1024.0 * 1024 * 1024;
    public static final double MB = 1024.0 * 1024;
    public static final double KB = 1024.0;
    
    protected String fileName;
    protected String timeLength;
    protected String filePath;
    protected String timeDate;
    protected String fileDisplayName;
    
    // 文件的大小
    protected String fileLength;
    
    public String getTimeLength(){
        return timeLength;
    }
    public long getFileTrueSize() {
        File temp = new File(filePath);
        if (!temp.isFile())
        {
            return 0;
        }
        // 获取文件的大小
        return temp.length();
    }

    public String getFileLength(){
        if("0".endsWith(fileLength)||"0B".endsWith(fileLength)){
            File temp = new File(filePath);

            long fileSize = temp.length();
            if (fileSize > GB)
            {
                fileLength =  String.format("%.2fGB", fileSize / GB);
            }
            else if (fileSize > MB)
            {
                fileLength = String.format("%.2fMB", fileSize / MB);
            }
            else if (fileSize > KB)
            {
                fileLength = String.format("%.2fKB", fileSize / KB);
            }
            else
            {
                fileLength = String.format("%dB", fileSize);
            }
            if(!("0".endsWith(fileLength)||"0B".endsWith(fileLength))){
                DBHelper.instance().update(this);
            }
        }
        return fileLength;
    }

    public int getWidth() {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options); // 此时返回的bitmap为null

        return  options.outWidth;
    }
    public int getHeight() {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options); // 此时返回的bitmap为null

        return  options.outHeight;
    }

    /*
    文件类型:视频8 音频9 图10
     */
    private int intFileType = -1;
    public void setIntFileType(int intFileType) {
        this.intFileType = intFileType;
    }

	//......省略了一些getter和setter方法

}

拿到路径后填充自己的文件信息类对象

    public static FileInfoStatus getLocalFile(String filePath) {

        File temp = new File(filePath);
        String pathFileName = temp.getName();
        L.d("pathFileName=%s", pathFileName);
        String[] arr = pathFileName.split("\\.");
        String pathHouzhui = arr[arr.length - 1]; //获取文件后缀

        if (!temp.isFile()) {
            return null;
        }

        FileInfoStatus fileInfo = new FileInfoStatus();
        fileInfo.setFilePath(temp.getPath());

        // 获取文件的大小
        long fileSize = temp.length();
        if (fileSize > GB) {
            fileInfo.setFileLength(String.format("%.2fGB", fileSize / GB));
        } else if (fileSize > MB) {
            fileInfo.setFileLength(String.format("%.2fMB", fileSize / MB));
        } else if (fileSize > KB) {
            fileInfo.setFileLength(String.format("%.2fKB", fileSize / KB));
        } else {
            fileInfo.setFileLength(String.format("%dB", fileSize));
        }

        // 设置日期和时长
        String timeDate = formatter.format(new Date(System.currentTimeMillis()));
        fileInfo.setTimeDate(timeDate);

		MediaMetadataRetriever mmr = new MediaMetadataRetriever();
        mmr.setDataSource(filePath);
        String duration = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
        fileInfo.setTimeLength(PublicUtils.msToHms(Long.parseLong(duration)));
        
        String newFileName = getTimeAndRandom();
        String uploadFilename = newFileName + "_upload0." + pathHouzhui;
        fileInfo.setFileDisplayName(pathFileName);
        fileInfo.setFileName(newFileName + "_" + 0 + "." + pathHouzhui);
        file.setIntFileType(8);   //设置文件类型是视频8

        return fileInfo;
    }

//几个判断文件类型的方法

	//是否是视频文件
    public static boolean isVideo(String path) {
        if (path.endsWith("mp4") || path.endsWith("MP4")) {
            return true;
        } else {
            return false;
        }
    }

	//是否是图片文件
    public static boolean isImage(String path) {
        if (path.endsWith("jpg") || path.endsWith("JPG") || path.endsWith("png") || path.endsWith("PNG")|| path.endsWith("jpeg")|| path.endsWith("JPEG")) {
            return true;
        } else {
            return false;
        }
    }

	//是否是音频文件
    public static boolean isAudio(String path) {
        if (path.endsWith("mp3") || path.endsWith("MP3") ) {
            return true;
        } else {
            return false;
        }
    }

视频文件的时长转换方法,转换后类似 00:00:00

public static String msToHms(long milliSecondTime) {

        int hour = (int) milliSecondTime / (60 * 60 * 1000);
        int minute = (int) (milliSecondTime - hour * 60 * 60 * 1000) / (60 * 1000);
        int seconds = (int) (milliSecondTime - hour * 60 * 60 * 1000 - minute * 60 * 1000) / 1000;

        if (seconds >= 60) {
            seconds = seconds % 60;
            minute += seconds / 60;
        }
        if (minute >= 60) {
            minute = minute % 60;
            hour += minute / 60;
        }

        String sh = "";
        String sm = "";
        String ss = "";
        if (hour < 10) {
            sh = "0" + String.valueOf(hour);
        } else {
            sh = String.valueOf(hour);
        }
        if (minute < 10) {
            sm = "0" + String.valueOf(minute);
        } else {
            sm = String.valueOf(minute);
        }
        if (seconds < 10) {
            ss = "0" + String.valueOf(seconds);
        } else {
            ss = String.valueOf(seconds);
        }

        return sh + ":" + sm + ":" + ss;
    }

三、本地视频文件的预览

展示出来后点击可进行视频预览,根据路径预览本地视频文件可参考另一篇文章:Android之播放本地视频和Url视频方法

四、完成,Nice!

猜你喜欢

转载自blog.csdn.net/qq_46269365/article/details/133942370