首页 > 解决方案 > 部分回收者按日期查看照片

问题描述

我创建了一个简单的画廊,显示手机上的所有图像。我想按日期(月份)划分图像,并且还想要一个包含最近拍摄的照片的顶部。请参考下图:

在此处输入图像描述

我该怎么做呢?

我的代码:

选择文件活动.Java

public class SelectFileActivity extends AppCompatActivity {

  RecyclerView recyclerView;
  GalleryAdapter galleryAdapter;
  List < String > images;
  TextView gallery_number;
  ImageView back_arrow;

  private static final int REQUEST_CODE_STORAGE_PERMISSION = 101;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_select_file);

    // Remove status bar
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

    // Initialize content
    gallery_number = findViewById(R.id.gallery_number);
    recyclerView = findViewById(R.id.recyclerview_gallery_images);
    back_arrow = findViewById(R.id.select_file_back_arrow);

    // Check for permission
    if (ContextCompat.checkSelfPermission(SelectFileActivity.this,
        Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {

      ActivityCompat.requestPermissions(SelectFileActivity.this,
        new String[] {
          Manifest.permission.READ_EXTERNAL_STORAGE
        }, REQUEST_CODE_STORAGE_PERMISSION);
    } else {
      loadImages();
    }
  }

  @Override
  public void onBackPressed() {
    startActivity(new Intent(this, HomeActivity.class));
    finish();
  }

  private void loadImages() {

    recyclerView.setHasFixedSize(true);

    // Set the number of pictures per a row
    recyclerView.setLayoutManager(new GridLayoutManager(this, 3));

    images = SelectImagesGallery.listOfImages(this);
    galleryAdapter = new GalleryAdapter(this, images, new GalleryAdapter.PhotoListener() {
      @Override
      public void onPhotoClick(String path) {
        // Do something with the selected photo
      }
    });

    recyclerView.setAdapter(galleryAdapter);
  }

  @Override
  public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    if (requestCode == REQUEST_CODE_STORAGE_PERMISSION) {
      if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {

        loadImages();

      } else {
        Toast.makeText(this, "Permission Denied", Toast.LENGTH_SHORT).show();
      }
    }
  }
}

GalleryAdapter.java

public class GalleryAdapter extends RecyclerView.Adapter < GalleryAdapter.ViewHolder > {

  private Context context;
  private List < String > images;
  protected PhotoListener photoListener;

  public GalleryAdapter(Context context, List < String > images, PhotoListener photoListener) {
    this.context = context;
    this.images = images;
    this.photoListener = photoListener;
  }

  @NonNull
  @Override
  public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    return new ViewHolder(
      LayoutInflater.from(context).inflate(R.layout.gallery_item, parent, false)
    );
  }

  @Override
  public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

    String image = images.get(position);

    // Load images to Glide
    Glide.with(context)
      .load(image)
      .transform(new CenterCrop(), new RoundedCorners(15))
      .into(holder.image);

    holder.itemView.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
        photoListener.onPhotoClick(image);
      }
    });
  }

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

  public class ViewHolder extends RecyclerView.ViewHolder {

    ImageView image;

    public ViewHolder(@NonNull View itemView) {
      super(itemView);

      image = itemView.findViewById(R.id.image);
    }
  }

  public interface PhotoListener {
    void onPhotoClick(String path);
  }
}

活动选择文件.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:background="@color/windowBackground"
    android:orientation="vertical"
    tools:context=".upload.SelectFileActivity">
    
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerview_gallery_images"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

标签: javaandroidxmlandroid-recyclerview

解决方案


TLDR

为它们创建两个 xml 和两个视图。在您的数据列表中还添加月份作为对象,并在您的onCreateViewHolder方法中,检查 viewType 并为此膨胀适当的 xml。

详细解答

我必须在我的一个项目中实现类似的东西,这就是我的适配器的样子。这只是一个示例应用程序,当然这些功能可以更好地实现。您需要通过更好的设计来实现它们。

首先你需要实现你自己的 RecyclerView 适配器:

public class RvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private List<GalleryBaseModel> _data;
    Context context ;

    public RvAdapter(Context context){
        this.context = context;
        this._data = new ArrayList<>();
    }
    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if (viewType == 1){ //DATE
            return new DateViewHolder(
                    LayoutInflater.from(context).inflate(R.layout.date_layout, parent, false)
            );
        }
        else { //Image
            return new ImageViewHolder(
                    LayoutInflater.from(context).inflate(R.layout.image_layout, parent, false)
            );
        }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        if (getItemViewType(position) == 1){
//            set date here
            FlexboxLayoutManager.LayoutParams layoutParams = (FlexboxLayoutManager.LayoutParams) holder.itemView.getLayoutParams();
            layoutParams.setFlexGrow(1.0f);
            layoutParams.width = MATCH_PARENT;
            holder.itemView.setLayoutParams(layoutParams);
        }
        else {
//        set image here
            FlexboxLayoutManager.LayoutParams layoutParams = (FlexboxLayoutManager.LayoutParams) holder.itemView.getLayoutParams();
            layoutParams.setFlexGrow(1.0f);
            layoutParams.width = getWidth();
            holder.itemView.setLayoutParams(layoutParams);
        }

    }

    /**
     * A function to calculate width of your image cardViews.
     * As it is a sample application I just return constant value, but you should calculate it.
     * For example screenWidth/3
     * @return Width of image cardView
     */
    public int getWidth(){
        return 200;
    }

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

    @Override
    public int getItemViewType(int position) {
        return _data.get(position).getType();
    }

    class DateViewHolder extends RecyclerView.ViewHolder{
        TextView dateTv;
        public DateViewHolder(@NonNull View itemView) {
            super(itemView);
            dateTv = itemView.findViewById(R.id.dateTv);
        }
    }

    class ImageViewHolder extends RecyclerView.ViewHolder{
        ImageView mImage;
        public ImageViewHolder(@NonNull View itemView) {
            super(itemView);
            mImage = itemView.findViewById(R.id.mImage);
        }
    }

    public void addItem(GalleryBaseModel item){
        this._data.add(item);
        notifyDataSetChanged();
    }
}

这是我的image_view.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView android:layout_width="match_parent"
    android:background="@android:color/black"
    android:layout_height="120dp"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginTop="10dp"
    android:layout_marginBottom="10dp"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        xmlns:app="http://schemas.android.com/apk/res-auto">

        <ImageView
            android:id="@+id/mImage"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

这是我的date_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
    android:id="@+id/dateTv"
    android:text="June 2020"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>

这是我的GalleryBaseModel.java哪个是需要在我的适配器中膨胀的对象的基本模型类。

public abstract class GalleryBaseModel {
    abstract int getType();
}

继承这个抽象类的所有类都需要实现getType()方法并返回它们实际的模型类型。例如,这里 1 用于我的日期模型,0 用于我的图像模型。由于这些非常简单,我不将它们包含在回答。

最后是我如何设置我的 recyclerView:

//this could be onCreate method of your activity or any other proper method in activity or fragment or ...
        adapter = new RvAdapter(getApplicationContext());
        flexboxLayoutManager = new FlexboxLayoutManager(getApplicationContext());
        flexboxLayoutManager.setJustifyContent(JustifyContent.SPACE_BETWEEN);
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(flexboxLayoutManager);

对于管理我使用的布局,您可以在此处FlexBoxLayoutManager找到有关它的更多信息,如果您打算使用它,请阅读文档并为其使用适当的配置。但是您可以使用任何其他您希望的布局管理器。

希望这对您有所帮助。


推荐阅读