我是靠谱客的博主 无聊狗,最近开发中收集的这篇文章主要介绍内容提供者 (获取媒体库图片显示出来)Android10.0 适配呈现效果,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

内容提供者 (获取媒体库图片显示出来)

  • 呈现效果
    • 设计步骤
      • 注意问题

Android 10.0 适配问题都解决了
项目源码.

呈现效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

设计步骤

  1. 第一步:先定义两个Activity,一个获取数据并用来展示,一个展示媒体库图片并提供选择
    MainActivity

     <Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:onClick="pickImages"
    android:text="获取图片"
    android:textSize="20dp" />
    <androidx.recyclerview.widget.RecyclerView
    android:id="@+id/showPicM"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
    

PackageImageActivity

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/image3" />
<TextView
android:id="@+id/finished_pic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="(0/9)完成"
android:textColor="#000000"
android:textSize="20dp"
android:onClick="finishedPic"
/>
</RelativeLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/showImages"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
  1. 第二步: Android6.0以后的动态申请权限。

     private void checkReadPermission() {
    int readPermission = checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
    int writePermission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
    if (readPermission != PackageManager.PERMISSION_GRANTED && writePermission != PackageManager.PERMISSION_GRANTED) {
    requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, READ_PERMISSION_CORD);
    }
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (requestCode == READ_PERMISSION_CORD) {
    if (grantResults.length == 2 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
    Log.d(TAG, "拥有权限");
    }
    }
    }
    
  2. 第三步 从MainActivity 跳转到 PackageImageActivity

    
    public void pickImages(View view) {
    Intent intent = new Intent(MainActivity.this, PackageImage.class);
    startActivity(intent);
    }
    

4. 第四步 使用LoaderManager 异步获取数据

	private void initLoaderManager() {
imageItemList.clear();
LoaderManager loaderManager = LoaderManager.getInstance(this);
loaderManager.initLoader(LOADER_ID, null, new LoaderManager.LoaderCallbacks<Cursor>() {
/**
* 因为图库图片可能较多,不能在主线程进行耗时操作
* 在子线程进行操作
* @param id
* @param args
* @return
一个CurSor 装载
*/
@NonNull
@Override
public Loader<Cursor> onCreateLoader(int id, @Nullable Bundle args) {
if (id == LOADER_ID) {
return new CursorLoader(PackageImage.this, MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.Images.Media._ID}, null, null, MediaStore.Images.Media.DATE_ADDED+" DESC");
}
return null;
}
/**
* 装载完成后调用
* @param loader
一个对象
* @param cursor
光标,包含所有图片信息。
*/
@Override
public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor cursor) {
if (cursor != null) {
while (cursor.moveToNext()) {
String id = cursor.getString(0);
//
**因为Android 10.0 以后进行分区存储。我们即使申请权限,也不能访问SD卡的内容。
//
因此如果这里获取path 后面使用Glide 加载图片会报FileNoFOUND错误。所以我们通过ID获取Uri**
Uri uri = Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,id);
imageItemList.add(uri);
adapter.setData(imageItemList);
}
}
}
/**
* 重新装载是调用
* @param loader
*/
@Override
public void onLoaderReset(@NonNull Loader<Cursor> loader) {
}
});
}
  1. 第五步 使用recyclerView 将获取的图片信息,展现出来

    @NonNull
    @Override
    public InnerHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_image, parent, false);
    //使用该方法,获取屏幕长度,将每一个图片尺寸设置x/3
    Point point = SizeUtils.getScreenSize(view.getContext());
    RecyclerView.LayoutParams layoutParams = new RecyclerView.LayoutParams(point.x / 3, point.y / 3);
    view.setLayoutParams(layoutParams);
    return new InnerHolder(view);
    }
    
  2. 第六步 在Adapter 里面暴露一个接口,用于将数据传出来

     public void setOnItemSelectedNum(onItemSelectedNum onItemSelectedNum){
    this.mOnItemSelectedNum = onItemSelectedNum;
    }
    public interface onItemSelectedNum{
    void onItemSelectedChange(List<Uri> list);
    }
    
  3. 第七步 设计事件,用于表示选中图片

     @Override
    public void onBindViewHolder(@NonNull InnerHolder holder, int position) {
    View view = holder.itemView;
    ImageView imageView = view.findViewById(R.id.iv);
    final View visibility = view.findViewById(R.id.visibility);
    final CheckBox select = view.findViewById(R.id.select);
    final Uri uri = mimageItems.get(position);
    Glide.with(imageView.getContext()).load(uri).into(imageView);
    //
    先根据状态来渲染,防止紊乱
    if (mselect.contains(uri)) {
    select.setButtonDrawable(R.drawable.image1);
    visibility.setVisibility(View.VISIBLE);
    } else {
    select.setButtonDrawable(R.drawable.image2);
    visibility.setVisibility(View.INVISIBLE);
    }
    imageView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    //
    如果已经没被选择,添加
    if (!mselect.contains(uri)) {
    if(mselect.size()>=9){
    Toast.makeText(select.getContext(),"最多选择"+MAX_SELECTED_PIC+"张图片",Toast.LENGTH_SHORT).show();
    }else{
    mselect.add(uri);
    select.setButtonDrawable(R.drawable.image1);
    visibility.setVisibility(View.VISIBLE);
    }
    } else {
    //
    如果已经被选择,删除,更改可见度
    mselect.remove(uri);
    select.setButtonDrawable(R.drawable.image2);
    visibility.setVisibility(View.INVISIBLE);
    }
    mOnItemSelectedNum.onItemSelectedChange(mselect);
    }
    });
    }
    
  4. 第八步 选择完成,将图片传回。需要使前后数据一致。我们使用一个PickerConfig(单例模式) 来实现。 在两个Activity都初始化它

     public class PickerConfig {
    //最大选择图片数量
    private int max_selected_pic = 1;
    private OnItemSelectedFinished monItemSelectedFinished = null;
    public OnItemSelectedFinished getMonItemSelectedFinished() {
    return monItemSelectedFinished;
    }
    private PickerConfig(){}
    private static PickerConfig pickerConfig;
    public static PickerConfig getInstance(){
    if(pickerConfig==null){
    pickerConfig =new PickerConfig();
    }
    return pickerConfig;
    }
    public void setOnItemSelectedFinished(OnItemSelectedFinished onItemSelectedFinished){
    this.monItemSelectedFinished = onItemSelectedFinished;
    }
    public interface OnItemSelectedFinished{
    void onItemSelectedFinished(List<Uri> list);
    }
    public int getMax_selected_pic() {
    return max_selected_pic;
    }
    public void setMax_selected_pic(int max_selected_pic) {
    this.max_selected_pic = max_selected_pic;
    }
    }
    
  5. 第九步, 两个Activity初始化上面方法。 选择完成 ,数据返回

     public void finishedPic(View view){
    //需要获取数据
    List<Uri> list = adapter.getMselect();
    //把数据通知给其他地方
    PickerConfig.OnItemSelectedFinished monItemSelectedFinished = mpickerConfig.getMonItemSelectedFinished();
    if(monItemSelectedFinished!=null){
    monItemSelectedFinished.onItemSelectedFinished(list);
    }
    //结束
    finish();
    }
    
  6. 第十步,将获取的数据在MainActivity 使用recyclView实现。
    可以如果返回图片少于3个,就按几列展示。大于三列的三列显示

    private void initConfig() {
    PickerConfig pickerConfig = PickerConfig.getInstance();
    pickerConfig.setMax_selected_pic(MAX_SELECTED_PIC);
    pickerConfig.setOnItemSelectedFinished(new PickerConfig.OnItemSelectedFinished() {
    @Override
    public void onItemSelectedFinished(List<Uri> list) {
    int horNum =1;
    if(list.size()<3){
    horNum =list.size();
    }else{
    horNum =3;
    }
    GridLayoutManager gridLayoutManager =new GridLayoutManager(MainActivity.this,horNum);
    recyclerView.setLayoutManager(gridLayoutManager);
    mainAdapter.setData(list,horNum);
    }
    });
    }
    

注意问题

1. Android10.0 为了保存隐私,不允许访问SD卡的等内容。我们需要使用
MediaStore.Images.Media 得到uri 不能使用path路径
2. Glide4.x 以上版本需要
implementation ‘com.github.bumptech.glide:glide:4.11.0’
annotationProcessor ‘com.github.bumptech.glide:compiler:4.11.0’
并且创建
@GlideModule
public class MyAppGlideModule extends AppGlideModule {
}
4. 如果没有报错,但图片没有加载出来。可能是因为适配器的设置长宽参数不合适

最后

以上就是无聊狗为你收集整理的内容提供者 (获取媒体库图片显示出来)Android10.0 适配呈现效果的全部内容,希望文章能够帮你解决内容提供者 (获取媒体库图片显示出来)Android10.0 适配呈现效果所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(35)

评论列表共有 0 条评论

立即
投稿
返回
顶部