Clicking on an image in RecycleView

Viewed 62

I am really new to AndroidStudio and I'm trying to make a sharing app. My purpose is to have an app that automatically loads up all the images on my phone(or in my phone's gallery, not that important) and display them on screen. Afterwards, I want to click on one of the images over there, and then use a Share button I made to send that photo to another person (it can be an MMS or any other application, the main problem is that this share button transmit the picture I clicked on most recently).

I don't know a lot about the specifics of Android Studio, meaning I know how to code (sort of) but I am unfamiliar with the possibilities of implementing this. My code is below.

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);
    Glide.with(context).load(image).into(holder.image);
    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            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);
}
}

ImagesGallery.java:

public class ImagesGallery {
    public static ArrayList<String> listofImages(Context context){
        Uri uri;
        Cursor cursor;
        int column_index_data, column_index_folder_name;
        ArrayList<String> listofAllImages=new ArrayList<>();
        String absolutePathOfImage;
        uri= MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        String[] projection={MediaStore.MediaColumns.DATA, MediaStore.Images.Media.BUCKET_DISPLAY_NAME};
        String orderBy= MediaStore.Video.Media.DATE_TAKEN;
        cursor=context.getContentResolver().query(uri, projection, null, null, orderBy+" DESC");
        column_index_data=cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
        while(cursor.moveToNext()){
            absolutePathOfImage=cursor.getString(column_index_data);
            listofAllImages.add(absolutePathOfImage);
        }
        return listofAllImages;
    }
}

MainActivity.java:

public class MainActivity extends AppCompatActivity {
    RecyclerView recyclerView;
    GalleryAdapter galleryAdapter;
    List<String> images;
    TextView gallery_number;
    private static final int MY_READ_PERMISSION_CODE=101;

@Override
protected void onCreate(Bundle savedInstanceState) {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 101);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    gallery_number=findViewById(R.id.gallery_number);
    recyclerView=findViewById(R.id.recyclerview_gallery_images);
    if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){
        ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, MY_READ_PERMISSION_CODE);
    } else {
        loadImages();
    }

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main_menu, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    if(item.getItemId()==R.id.share_menu){
        Intent shareIntent = new Intent();
        shareIntent.setAction(Intent.ACTION_SEND);
        Uri uriToImage=Uri.parse("android.resource://com.example.tutorialpaper5/"+R.drawable.test);
        shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);
        shareIntent.setType("image/jpeg");
        startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.app_name)));
    } else{
        return super.onOptionsItemSelected(item);
    }
    return true;
}

private void loadImages(){
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(new GridLayoutManager(this, 4));
    images=ImagesGallery.listofImages(this);
    galleryAdapter=new GalleryAdapter(this, images, new GalleryAdapter.PhotoListener() {
        @Override
        public void onPhotoClick(String path) {
            Toast.makeText(MainActivity.this, ""+path, Toast.LENGTH_LONG).show();
        }
    });
    recyclerView.setAdapter(galleryAdapter);
    gallery_number.setText("Photos +("+images.size()+")");

}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if(requestCode==MY_READ_PERMISSION_CODE){
        if(grantResults[0]==PackageManager.PERMISSION_GRANTED){
            Toast.makeText(this, "read external storage permission granted", Toast.LENGTH_LONG).show();
            loadImages();
        } else {
            Toast.makeText(this, "Read external storage permission denied", Toast.LENGTH_LONG).show();
        }
    }
}
}

You will notice that in my onOptionsItemSelected class I just threw in a picture I had in the drawable directory to see if the share button actually works. It does, now I just need some way for it memorize my last clicked photo and throw it in that Intent. But again, I am not sure if that is possible.

1 Answers

There are multiple options, here are two simple solutions just to link your code parts.

Suggestion with minimal changes in your logic:

You can just save the onPhotoClick(String path) to a field that will defined in the activity class scope and then use this field in the onOptionsItemSelected adding some code parts:

public class MainActivity extends AppCompatActivity {
    String clickedImagePath = null
// ...
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    if(item.getItemId()==R.id.share_menu){
       if (clickedImagePath  != null) {
         // The code you had for sharing with changing line for uriToImage
         Uri uriToImage=Uri.parse(clickedImagePath);
       } else { 
         // maybe show some error than nothing selected
       }
    }
}

// ...
        public void onPhotoClick(String path) {
            Toast.makeText(MainActivity.this, ""+path, Toast.LENGTH_LONG).show();
            clickedImagePath = path
        }
// ...

Maybe a better UX

Remove the onOptionsItemSelected completely and move the intent code to the onPhotoClick listener.

    @Override
    public void onPhotoClick(String path) {
        Toast.makeText(MainActivity.this, ""+path, Toast.LENGTH_LONG).show();
        Intent shareIntent = new Intent();
        shareIntent.setAction(Intent.ACTION_SEND);
        Uri uriToImage=Uri.parse(path); // <-- Don't forget to fix the path
        shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);
        shareIntent.setType("image/jpeg");
        MainActivity.this.startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.app_name)));

    }
Related