The problem in short is that I cannot use this function to show a dialog.
public class Page_6Fragment extends android.support.v4.app.Fragment {
RecyclerView recyclerView;
List<Customer> customers;
CustomerAdapter adapter;
View rootView;
String TAG = "MainActivity - ";
Context context;
API api;
Activity a;
public static Page_6Fragment newInstance() {
Page_6Fragment fragment = new Page_6Fragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.activity_customer, container, false);
// View rootView = inflater.inflate(R.xml.pref, container, false);
// Intent intent = new Intent(PreferenceDemoActivity.this,PrefsActivity.class);
// startActivity(intent);
this.context = getActivity();
recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
customers = new ArrayList<>();
adapter = new CustomerAdapter(context, customers);
adapter.setLoadMoreListener(new CustomerAdapter.OnLoadMoreListener(){
#Override
public void onLoadMore() {
recyclerView.post(new Runnable() {
#Override
public void run() {
int index = customers.size() - 1;
loadMore(index);
}
});
//Calling loadMore function in Runnable to fix the
// java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling error
}
});
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
//recyclerView.addItemDecoration(new VerticalLineDecorator(2));
recyclerView.setAdapter(adapter);
api = ServiceGenerator.createService(API.class);
load(0);
return rootView;
}
private void load(int index){
Call<List<Customer>> call = api.getCustomer(index);
call.enqueue(new Callback<List<Customer>>(){
#Override
public void onResponse(Call<List<Customer>> call, Response<List<Customer>> response){
// Toast.makeText(getActivity(), "tost "+response.body().get(0).post_writer, Toast.LENGTH_LONG).show();
// Log.i("TRUE_TRUE","Yes"+response.body().get(0).title);
if(response.isSuccessful()){
customers.addAll(response.body());
adapter.notifyDataChanged();
// Toast.makeText(MainActivity.this, "tost "+response.body().get(0).post_writer, Toast.LENGTH_LONG).show();
}else{
Log.e(TAG," Response Error "+String.valueOf(response.code()));
}
}
#Override
public void onFailure(Call<List<Customer>> call, Throwable t) {
Log.e(TAG," Response Error "+t.getMessage());
}
});
}
private void loadMore(int index){
//add loading progress view
customers.add(new Customer("load"));
adapter.notifyItemInserted(customers.size()-1);
Call<List<Customer>>call = api.getCustomer(index);
call.enqueue(new Callback<List<Customer>>(){
#Override
public void onResponse(Call<List<Customer>> call, Response<List<Customer>>response) {
if(response.isSuccessful()){
// remove loading view .......
customers.remove(customers.size()-1);
List<Customer>result=response.body();
if(result.size()>0){
// add loaded data
customers.addAll(result);
}else{//result size 0 means there is no more data available at server
adapter.setMoreDataAvailable(false);
//telling adapter to stop calling load more as no more server data available
Toast.makeText(context,"No More Data Available",Toast.LENGTH_LONG).show();
}
adapter.notifyDataChanged();
}else{
Log.e(TAG," Load More Response Error "+String.valueOf(response.code()));
}
}
#Override
public void onFailure(Call<List<Customer>>call,Throwable t) {
Log.e(TAG," Load More Response Error "+t.getMessage());
}
});
}
public void showDialog(){
Dialog dialog = new Dialog(context);
dialog.setCancelable(true);
View view = getActivity().getLayoutInflater().inflate(R.layout.layout, null);
dialog.setContentView(view);
dialog.show();
}
}
// class to call function
package com.example.android.wacher.adapters;
import android.app.Dialog;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.example.android.wacher.R;
import com.example.android.wacher.activities.HomeActivity;
import com.example.android.wacher.fragments.Page_6Fragment;
import com.example.android.wacher.models.Customer;
import java.util.List;
/**
* Created by cca on 23/12/2018.
*/
public class CustomerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public final int TYPE_MOVIE = 0;
public final int TYPE_LOAD = 1;
static Context context;
List<Customer> customers;
OnLoadMoreListener loadMoreListener;
boolean isLoading = false, isMoreDataAvailable = true;
public CustomerAdapter(Context context, List<Customer> customers) {
this.context = context;
this.customers = customers;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType==TYPE_MOVIE){
return new CustomerHolder(inflater.inflate(R.layout.row_movie,parent,false));
}else{
return new LoadHolder(inflater.inflate(R.layout.row_load,parent,false));
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
if(position>=getItemCount()-1 && isMoreDataAvailable && !isLoading && loadMoreListener!=null){
isLoading = true;
loadMoreListener.onLoadMore();
}
if(getItemViewType(position)==TYPE_MOVIE){
((CustomerHolder)holder).bindData(customers.get(position));
if(((CustomerHolder)holder).buttonViewOption != null)((CustomerHolder)holder).buttonViewOption.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// call function
Page_6Fragment.newInstance().showDialog();
}
});
}
}
#Override
public int getItemViewType(int position) {
if(customers.get(position).type.equals("movie")){
return TYPE_MOVIE;
}else{
return TYPE_LOAD;
}
}
#Override
public int getItemCount(){
return customers.size();
}
/* VIEW HOLDERS */
static class CustomerHolder extends RecyclerView.ViewHolder{
TextView tvTitle;
TextView tvRating;
Button buttonViewOption;
public CustomerHolder(View itemView) {
super(itemView);
tvTitle=(TextView)itemView.findViewById(R.id.title);
tvRating=(TextView)itemView.findViewById(R.id.rating);
buttonViewOption = (Button) itemView.findViewById(R.id.textViewOptions);
}
void bindData(Customer cust){
tvTitle.setText(cust.name);
tvRating.setText(cust.title);
}
}
static class LoadHolder extends RecyclerView.ViewHolder{
public LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
/* notifyDataSetChanged is final method so we can't override it
call adapter.notifyDataChanged(); after update the list
*/
public void notifyDataChanged(){
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener{
void onLoadMore();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
}
When I call the ShowDialog function, an error occurs (pasted below.)
I don't know why this function does not work within the Page_6Fragment class.
Process: com.example.android.wacher, PID: 11335
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources$Theme android.content.Context.getTheme()' on a null object reference
at android.app.Dialog.<init>(Dialog.java:173)
at android.app.Dialog.<init>(Dialog.java:147)
at com.example.android.wacher.fragments.Page_6Fragment.showDialog(Page_6Fragment.java:153)
at com.example.android.wacher.adapters.CustomerAdapter$1.onClick(CustomerAdapter.java:70)
at android.view.View.performClick(View.java:5609)
at android.view.View$PerformClick.run(View.java:22259)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
You can't use Page_6Fragment.newInstance().showDialog(); .
Method public void showDialog() should be private because of it's handle Context reference.
To show Dialog from else where you should use
public void showDialog(Context context){
Dialog dialog = new Dialog(context);
dialog.setCancelable(true);
dialog.setContentView(R.layout.layout);
dialog.show();
}
And no need to inflate layout to set content view
Related
Update: One of the problems is solved: Now updateList is resolved, the problem was that I defined mAdapter as RecyclerView.Adapter instead of MyAdapter. But now even though I am getting data, nothing shows up on the list, it's empty
--------------------ORIGINAL POST--------------------
I want to update my RecyclerView using DiffUtil to prevent duplicates.
I have 4 classes: The User class, the Activity class where I set data, the Adapter class and the DiffUtil class. I am not sure I combine all these 4 correctly.
This is the User class:
public class User {
private String mUserId;
private Uri mImageUrl;
public User(String userId, String imageUrl) {
mUserId = userId;
mImageUrl = Uri.parse(imageUrl);
}
public String getUserId() {
return mUserId;
}
public Uri getImageUrl() {
return mImageUrl;
}
}
This is how I set data dynamically (I keep getting new Json arrays from the server containing user id's to be displayed, then I set the user image from Firebase storage): (It's a function invoked by an onClick listener:)
This is the method call from the fragment:
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
updateUsersList();
}
});
This is the function:
private void updateUsersList() {
#Override
public void onResponse(JSONArray response) { // the JSON ARRAY response of user ids ["uid1", "uid334", "uid1123"]
myDataset.clear(); // clear dataset to prevent duplicates
for (int i = 0; i < response.length(); i++) {
try {
String userKey = response.get(i).toString(); // the currently iterated user id
final DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference userKeyRef = rootRef.child("users").child(userKey); // reference to currently iterated user
ValueEventListener listener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
myDataset.add(new User(dataSnapshot.getKey(), dataSnapshot.child("imageUrl").getValue().toString())); //add new user: id and image url
mAdapter.updateList(myDataset); // cannot resolve this method, why?
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage());
}
};
userKeyRef.addListenerForSingleValueEvent(listener);
}
catch (JSONException e) { Log.d(TAG, "message " + e); }
}
}
This is how my DiffUtil class looks like:
public class MyDiffUtilCallBack extends DiffUtil.Callback{
ArrayList<User> oldUsers;
ArrayList<User> newUsers;
public MyDiffUtilCallBack(ArrayList<User> newUsers, ArrayList<User> oldUsers) {
this.newUsers = newUsers;
this.oldUsers = oldUsers;
}
#Override
public int getOldListSize() {
return oldUsers.size();
}
#Override
public int getNewListSize() {
return newUsers.size();
}
#Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldUsers.get(oldItemPosition).getUserId().equals( newUsers.get(newItemPosition).getUserId());
}
#Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldUsers.get(oldItemPosition).equals(newUsers.get(newItemPosition));
}
#Nullable
#Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
//you can return particular field for changed item.
return super.getChangePayload(oldItemPosition, newItemPosition);
}
}
And this is my adapter:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private ArrayList<User> mDataset;
private MyViewHolder myHolder;
private User user;
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView singleItemTextView;
public ImageView singleItemImage;
public View layout;
public ConstraintLayout constraintLayout;
public MyViewHolder(View v) {
super(v);
layout = v;
singleItemImage = (ImageView) v.findViewById(R.id.icon);
singleItemTextView = (TextView) v.findViewById(R.id.singleitemtv);
constraintLayout = (ConstraintLayout) v.findViewById(R.id.nbConstraintLayout);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(ArrayList<User> myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.nb_image_view, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
myHolder = holder;
user = mDataset.get(position);
Uri userImage = user.getImageUrl();
myHolder.singleItemTextView.setText(user.getUserId());
Glide.with(myHolder.itemView.getContext() /* context */)
.load(userImage)
.into(myHolder.singleItemImage);
myHolder.constraintLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Context context = v.getContext();
Intent intent = new Intent(v.getContext(), DisplayUserActivity.class);
context.startActivity(intent);
}
});
}
public void updateList(ArrayList<User> newList) {
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new MyDiffUtilCallBack(this.mDataset, newList));
diffResult.dispatchUpdatesTo(this);
}
}
I am not sure I combine all the classes correctly (my first time using DiffUtil), and I also get cannot resolve method updateList(?)
What am I doing wrong?
This is how I define mAdapter in my Fragment:
public class MyFragment extends Fragment {
private ArrayList<User> myDataset;
private RecyclerView.Adapter mAdapter;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
rootView = inflater.inflate(R.layout.fragment_lks, container, false);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
myDataset = new ArrayList<User>();
mAdapter = new MyAdapter(myDataset);
The problem comes from definition of mAdapter. You defined it as RecyclerView.Adapter which is super class of your MyAdapter and it does not contain updateList(). You should change it as following:
private MyAdapter mAdapter;
Updated 1/13/2019:
I've revised your adapter with AsyncListDiffer which calculates the diffrence asynchronously then applies it to the adapter.
MyAdapter.java
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.constraint.ConstraintLayout;
import android.support.v7.recyclerview.extensions.AsyncListDiffer;
import android.support.v7.util.DiffUtil;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import java.util.List;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private AsyncListDiffer<User> mAsyncListDiffer;
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView singleItemTextView;
public ImageView singleItemImage;
public View layout;
public ConstraintLayout constraintLayout;
public MyViewHolder(View v) {
super(v);
layout = v;
singleItemImage = (ImageView) v.findViewById(R.id.icon);
singleItemTextView = (TextView) v.findViewById(R.id.singleitemtv);
constraintLayout = (ConstraintLayout) v.findViewById(R.id.nbConstraintLayout);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter() {
DiffUtil.ItemCallback<User> diffUtilCallback = new DiffUtil.ItemCallback<User>() {
#Override
public boolean areItemsTheSame(#NonNull User newUser, #NonNull User oldUser) {
return newUser.getUserId().equals(oldUser.getUserId());
}
#Override
public boolean areContentsTheSame(#NonNull User newUser, #NonNull User oldUser) {
return newUser.equals(oldUser);
}
};
mAsyncListDiffer = new AsyncListDiffer<>(this, diffUtilCallback);
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.nb_image_view, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
User user = mAsyncListDiffer.getCurrentList().get(position);
Uri userImage = user.getImageUrl();
holder.singleItemTextView.setText(user.getUserId());
Glide.with(holder.itemView.getContext() /* context */)
.load(userImage)
.into(holder.singleItemImage);
holder.constraintLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Context context = v.getContext();
Intent intent = new Intent(v.getContext(), DisplayUserActivity.class);
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return mAsyncListDiffer.getCurrentList().size();
}
public void updateList(List<User> newList) {
mAsyncListDiffer.submitList(newList);
}
}
User.java
public class User {
private String mUserId;
private Uri mImageUrl;
public User(String userId, String imageUrl) {
mUserId = userId;
mImageUrl = Uri.parse(imageUrl);
}
public String getUserId() {
return mUserId;
}
public Uri getImageUrl() {
return mImageUrl;
}
#Override
public boolean equals(Object other) {
if (other instanceof User) {
User user = (User) other;
return mUserId.equals(user.getUserId()) && mImageUrl.equals(user.getImageUrl());
} else {
return false;
}
}
}
In addition to #aminography's answer, I suggest you to use ListAdapter, a RecyclerView.Adapter implementation that makes it easier to update you RecyclerView with the correct animations. This class is included in the recyclerview support library.
Below is an example of usage based on your use case:
public class MyAdapter extends ListAdapter<User, UserViewHolder> {
public MyAdapter() {
super(new UserDiffCallback());
}
public UserViewHolder onCreateViewHolder(int position, int viewType) { ... }
public void onBindViewHolder(UserViewModel holder, int position) {
User userAtPosition = getItem(position); // getItem is a protected method from ListAdapter
// Bind user data to your holder...
}
}
public class UserDiffCallback extends DiffUtil.ItemCallback<User> {
#Override
public boolean areItemsTheSame(#NonNull User oldUser, #NonNull User newUser) {
return oldUser.getUserId().equals(newUser.getUserId());
}
#Override
public boolean areContentsTheSame(#NonNull User oldUser, #NonNull User newUser) {
// No need to check the equality for all User fields ; just check the equality for fields that change the display of your item.
// In your case, both impact the display.
return oldUser.getUserId().equals(newUser.getUserId())
&& (oldUser.getImageUrl() == null) ? newUser.getImageUrl() == null : oldUser.getImageUrl().equals(newUser.getImageUrl());
}
}
Then, when you need to update the list with new users, call myAdapter.submitList(newList). Juste like with AsyncListDiffer, the diff between the two list is calculated on a background Thread.
Modify your method:
public void updateList(ArrayList<User> newList) {
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new MyDiffUtilCallBack(this.mDataset, newList));
this.mDataSet.clear()
this.mDataSet.addAll(newList)
diffResult.dispatchUpdatesTo(this);
}
Looks like
public void onBindViewHolder(#NonNull ViewHolder holder, int position, #NonNull List<Object> payloads) not implemented
Implement this to use DiffUtils properly, as this method will be called for the changes, and based on the payload you can update your recyclerview items instead of calling notifyDataSetChanged()
So I have a RecyclerView that displays a list of open games in a lobby. Each time the RecyclerView is updated, a button is added to the screen and I want to make it so that whenever a user clicks that button, it gets the ID of the section it is in.
So, games are added to database like this.
public void createLobbyGame () {
User current = new User(userName, 0, getSide());
String id = FCGames.push().getKey();
gameMaker = new GameMaker(current, null, 0, numGames, false, false);
FCGames.child(id)
.setValue(gameMaker).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(FlipCoinLobby.this, "Game creation successful.", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(FlipCoinLobby.this, task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
}
And that creates a node in my database that looks like this:
So right now the ID is set at 0 but that's just because I forgot to make the ID equal to the name of the node.
So when something is added to my database, it is drawn in the app with a button. I am not sure how to make this button display the ID of the database node that it correlates to.
This is the clicklistener I have setup for the button in my ViewHolder class
Button joinButton = itemView.findViewById(R.id.joinRV);
joinButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(), gm.getId(), Toast.LENGTH_SHORT).show();
}
});
Just having the getId() method called does not work at all, and I wasn't expecting it to. But I am kind of lost on how to grab the correlating ID of the button whenever I click it
Adapter Class:
package com.example.brent.fifty_fifty;
import android.content.Intent;
import android.util.Log;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.content.Context;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
import static android.view.LayoutInflater.*;
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {
GameMaker gm;
private OnItemClickListener listener;
private List<String> mData;
private LayoutInflater mInflater;
private ItemClickListener mClickListener;
// data is passed into the constructor
MyRecyclerViewAdapter(Context context, List<String> data) {
this.mInflater = from(context);
this.mData = data;
}
public MyRecyclerViewAdapter(List<String> data, OnItemClickListener listener) {
this.mData = data;
this.listener = listener;
}
public interface OnItemClickListener {
void onItemClick(String id);
}
// inflates the row layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.recyclerview_row, parent, false);
return new ViewHolder(view);
}
// binds the data to the TextView in each row
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
String userName = mData.get(position);
//Double wager = Double.parseDouble(mData.get(position));
holder.userName.setText(userName);
//holder.wager.setText(wager.toString());
}
// total number of rows
#Override
public int getItemCount() {
return mData.size();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView userName, wager;
RelativeLayout parentLayout;
ViewHolder(View itemView) {
super(itemView);
userName = itemView.findViewById(R.id.UsernameRV);
//wager = itemView.findViewById(R.id.wagerRV);
itemView.setOnClickListener(this);
Button joinButton = itemView.findViewById(R.id.joinRV);
joinButton.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
listener.onItemClick(data);
Toast.makeText(itemView.getContext(), "It worked", Toast.LENGTH_SHORT).show();
}
});
}
public void bind(final String data, final OnItemClickListener listener) {
}
public void onBindViewHolder(ViewHolder holder, int position) {
holder.bind(mData.get(position), listener);
}
#Override
public void onClick(View view) {
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
}
}
// convenience method for getting data at click position
String getItem(int id) {
return mData.get(id);
}
// allows clicks events to be caught
void setClickListener(ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}
}
Please have a look at implementation of interface as Listener for recyclerview.
Please look this implementation. This is good one if you are using JAVA.
Here clicklistener is set on itemView you just need to replace itemView with your button.
public class MyRecyclerViewAdapter extends RecyclerView.Adapter< MyRecyclerViewAdapter.ViewHolder> {
public interface OnButtonClickListener {
void onButtonClick(String id);
}
private final List<String> items;
private final OnButtonClickListener listener;
public MyRecyclerViewAdapter(List<String> items, OnButtonClickListener listener) {
this.items = items;
this.listener = listener;
}
#Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout. recyclerview_row, parent, false);
return new ViewHolder(v);
}
#Override public void onBindViewHolder(ViewHolder holder, int position) {
holder.bind(items.get(position), listener);
}
#Override public int getItemCount() {
return items.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
private Button joinButton;
public ViewHolder(View itemView) {
super(itemView);
joinButton = (Button) itemView.findViewById(R.id. joinRV);
}
public void bind(final String id, final OnButtonClickListener listener) {
joinButton.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
listener.onItemClick(id);
}
});
}
}}
For your activity :
recycler.setAdapter(new MyRecyclerViewAdapter(items, new MyRecyclerViewAdapter.OnButtonClickListener() {
#Override public void onButtonClick(String id) {
Toast.makeText(this, id, Toast.LENGTH_LONG).show();
}}));
My viewpager adapter is in another fragment(i.e. in main fragment) i.e. i used viewpager in another fragment.so viewpager adapter having 2 fragments.
I am getting heart rate value continuously from main fragment and need to send it to viewpager adapter.then viewpager adapter send this value to fragment and upadate the textview here.
//Main Fragment were i initialize fragmentpageradapter with updated heart rate value:-((readingdata)samplePagerAdapter).passdata(value);
used interface to update value:-
public interface readingdata
{
void passdata(int value);
}
//Adapter code:-
public class SamplePagerAdapter extends FragmentStatePagerAdapter implements readingdata {
private final Random random = new Random();
private int mSize = 2;
private int heart_rate;
FragmentManager fm;
private Map<Integer, String> mFragmentTags;
public SamplePagerAdapter(FragmentActivity activity, FragmentManager supportFragmentManager, int heart) {
super(supportFragmentManager);
fm = supportFragmentManager;
mFragmentTags = new HashMap<Integer, String>();
}
#Override
public int getCount() {
return mSize;
}
#Override
public Fragment getItem(int position) {
Fragment f = null;
if (position == 0) {
f = new MyFragment().newInstance(heart_rate);
} else if (position == 1) {
f = new SecondFragment();
}
return f;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Object object = super.instantiateItem(container, position);
if (object instanceof Fragment) {
Fragment fragment = (Fragment) object;
String tag = fragment.getTag();
mFragmentTags.put(position, tag);
}
return object;
}
public Fragment getFragment(int position) {
Fragment fragment = null;
String tag = mFragmentTags.get(position);
if (tag != null) {
fragment = fm.findFragmentByTag(tag);
}
return fragment;
}
#Override
public void passdata(int value) {
heart_rate=value;
}
}
//Fragment code were textview updated on regular interval
public class MyFragment extends Fragment{
private int heart_rate;
private ArcProgress arc_progress;
private TextView tv_heartrate;
private Handler handler;
private Runnable runnable;
private View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle saveBundle) {
view = inflater.inflate(R.layout.ecg_layout, container, false);
handler=new Handler();
arc_progress = (ArcProgress) view.findViewById(R.id.arc_progress);
tv_heartrate = (TextView) view.findViewById(R.id.tv_heart_rate);
handler=new Handler();
handler.post(runnable = new Runnable() {
#Override
public void run() {
MyFragment myFragment=new MyFragment();
arc_progress.setProgress(heart_rate);
tv_heartrate.setText(String.valueOf(heart_rate));
handler.postDelayed(this, 1000);
}
});
return view;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
public static Fragment newInstance(int heartvalue) {
MyFragment f = new MyFragment();
f.heart_rate = heartvalue;
return f;
}
}
So how should i update textview continuously inside the fragment?
In MainFragment
private static HeartRateListener heartRateListener;
public static void setHeartRateListener(HeartRateListener listener){
heartRateListener = listener;
}
public static interface HeartRateListener{
void onHeartRate(int yourValue);
}
// Send your continuously updated value
heartRateListener.onHeartRate(yourValue);
In ViewPager Fragment (inside onViewCreated())
MainFragment.setHeartRateListener(new MainFragment.HeartRateListener() {
#Override
public void onHeartRate(int yourValue) {
// Update your textview with yourValue
}
});
create Method
public void updateScreenData(String text)
{
tv_heartrate.setText(text);
}
in fragment and then call this method from activity
make sure that fragment reference is not null whenever call this method
Take Help from this and save reference to view you are inflating
package com.mtg.workapp_v2.listing.wanted.add_wanted;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.TextView;
import com.mtg.classes.AddressView;
import com.mtg.classes.ListingVisibilityLayout;
import com.mtg.utils.CommonMethods;
import com.mtg.workapp.R;
public class WantedBasicInfoFragment extends Fragment implements View.OnClickListener{
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
View FragmentView ;
Context myContext;
TextView text_continue;
EditText edit_title;
EditText edit_description;
private OnFragmentInteractionListener mListener;
//this is add by ahsan according to new design
ListingVisibilityLayout listingVisibilityLayout = null;
public WantedBasicInfoFragment() {
}
public static WantedBasicInfoFragment newInstance(String param1, String param2) {
WantedBasicInfoFragment fragment = new WantedBasicInfoFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
FragmentView= inflater.inflate(R.layout.fragment_wanted_basic, container, false);
init();
return FragmentView;
}
/********************************************************************************/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
/********************************************************************************/
public void setListener(OnFragmentInteractionListener listener) {
this.mListener = listener;
}
/********************************************************************************/
public void setInitValues()
{
}
/***********************************************************************************/
public void updateScreenData()
{
edit_title.setText(wantedInformation.csName);
edit_description.setText(wantedInformation.csDescription);
}
/***********************************************************************************/
public void init()
{
myContext=getActivity();
text_continue=(TextView) FragmentView.findViewById(R.id.text_continue);
edit_title = (EditText) FragmentView.findViewById(R.id.edit_title);
edit_description = (EditText) FragmentView.findViewById(R.id.edit_description);
text_continue.setOnClickListener(this);
edit_title.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
wantedInformation.csListingLanguage = CommonMethods.getInputLanguage(myContext);
}
#Override
public void afterTextChanged(Editable s) {
wantedInformation.csListingLanguage = CommonMethods.getInputLanguage(myContext);
}
});
initVisibilitySpinner();
}
/***********************************************************************************/
public void initVisibilitySpinner()
{
listingVisibilityLayout = new ListingVisibilityLayout(myContext);
View visibilityView = (View)FragmentView.findViewById(R.id.id_visibility_layout);
listingVisibilityLayout.ListingVisibilityInit(visibilityView);
}
/***********************************************************************************/
#Override
public void onClick(View view) {
int itemID = view.getId();
switch (itemID) {
case R.id.text_continue:
{
moveToNextScreen(true);
}
}
}
/***********************************************************************************/
public void moveToNextScreen(boolean isContinueClicked)
{
String csName = edit_title.getText().toString().trim();
String csDescription = edit_description.getText().toString().trim();
if(csName.length() <= 0 && csDescription.toString().length() <= 0)
{
CommonMethods.showMessageBox("", getResources().getString(R.string.id_please_enter_name_and_description), myContext);
return;
}
else if(csName.length() <= 0)
{
CommonMethods.showMessageBox("", getResources().getString(R.string.id_please_enter_name), myContext);
return;
}
else if(csDescription.length() <= 0)
{
CommonMethods.showMessageBox("", getResources().getString(R.string.id_please_enter_description), myContext);
return;
}
else if(listingVisibilityLayout.selectedProfileVisibility.csOptionID.equalsIgnoreCase("-1"))
{
CommonMethods.showMessageBox("", getResources().getString(R.string.id_select_visibility_option_msg), myContext);
return;
}
wantedInformation.csName = csName;
wantedInformation.csDescription = csDescription;
wantedInformation.visibilityOption = listingVisibilityLayout.selectedProfileVisibility;
//MH: If continue clicked then continue Button listener will be called
//MH: If only tick is clicked in Edit Mode then onUpdate listener will be called
//MH: and data will be updated before sent to api
//MH: The below statements are repeated in all fragments of Wanted
if(isContinueClicked)
mListener.continueButtonPressed(wantedInformation);
else
mListener.onUpdate(wantedInformation);
}
}
Long post, thanks for taking the time to look through this
I have been struggling with this issue for a while now. I have an SQLiteDatabase which stores a shoe's brand name, name of shoe, and a byte image of the shoe. I was able to load all of the information to a recyclerview via a content provider. But it seems when I try and load the information to the details of each item in the recycler view, the details activity is filled with the wrong information, it returns a completely different entry other than the one I selected.
The solutions I've seen in many youtube videos have contained me creating ArrayLists to store the information, but I find that very hard to do using my SQLiteDatabase information.
Here are the classes I have...
My Closet.java class(with my getter methods)
package com.example.android.myshoecloset;
import android.database.Cursor;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by man on 12/21/2017.
*/
public class Closet
{
private static final String TAG = Closet.class.getSimpleName();
//Brand name
private final String brandName;
//Shoe Name
private final String shoeName;
//Image of the shoe
private final String shoeImage;
public Closet(String brandName, String shoeName, String shoeImage)
{
this.brandName = brandName;
this.shoeName = shoeName;
this.shoeImage = shoeImage;
}
public Closet(Cursor cursor)
{
this.brandName = null;
this.shoeName = null;
this.shoeImage = null;
}
public String getShoeImageName()
{
return shoeImage;
}
public String getBrandName()
{
return brandName;
}
public String getShoeName()
{
return shoeName;
}
}
My Adapter Class(CustomAdapter.java)
package com.example.android.myshoecloset.data;
/*Assume appropriate imports*/
/**
* Created by man on 11/23/2017.
*/
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.TaskHolder> {
private Cursor mCursor;
private Context mContext;
public static String shoeName;
public static String brandName;
public static byte[] byteArray;
public CustomAdapter(Context mContext) {
this.mContext = mContext;
}
public CustomAdapter()
{
mContext = null;
}
/* ViewHolder for each task item */
public class TaskHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView shoeBrandName;
public TextView shoeName;
public ImageView shoeImage;
public LinearLayout linearLayout;
public TaskHolder(final View itemView) {
super(itemView);
itemView.setOnClickListener(this);
shoeBrandName = (TextView) itemView.findViewById(R.id.textBrandName);
shoeImage = (ImageView) itemView.findViewById(R.id.shoeImage);
shoeName = (TextView) itemView.findViewById(R.id.textShoeName);
linearLayout = (LinearLayout) itemView.findViewById(R.id.linear_closet);
}
#Override
public void onClick(View v) {
Intent i = new Intent(v.getContext(), ShoeDetailActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
v.getContext().startActivity(i);
}
}
#Override
public TaskHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mContext);
View itemView = inflater
.inflate(R.layout.text_row_item, parent, false);
return new TaskHolder(itemView);
}
#Override
public void onBindViewHolder(TaskHolder holder, int position) {
int idIndex = mCursor.getColumnIndex(DatabaseContract.ShoeColumns._ID);
int imgValue = mCursor.getColumnIndex(DatabaseContract.ShoeColumns.SHOE_IMAGE);
int shoeBrandName = mCursor.getColumnIndex(DatabaseContract.ShoeColumns.SHOE_BRAND);
int shoeName = mCursor.getColumnIndex(DatabaseContract.ShoeColumns.SHOE_NAME);
mCursor.moveToPosition(position);
final int id = mCursor.getInt(idIndex);
byte[] shoeImg = mCursor.getBlob(imgValue);
String brandNameStr = mCursor.getString(shoeBrandName);
String shoeNameStr = mCursor.getString(shoeName);
Bitmap bmp = BitmapFactory.decodeByteArray(shoeImg, 0, shoeImg.length);
holder.itemView.setTag(id);
holder.shoeImage.setImageBitmap(Bitmap.createScaledBitmap(bmp, 100, 100, false));
holder.shoeBrandName.setText(brandNameStr);
holder.shoeName.setText(shoeNameStr);
holder.getAdapterPosition();
CustomAdapter.shoeName = shoeNameStr;
CustomAdapter.brandName = brandNameStr;
CustomAdapter.byteArray = mCursor.getBlob(imgValue);
}
#Override
public int getItemCount() {
return (mCursor != null) ? mCursor.getCount() : 0;
}
public void swapCursor(Cursor cursor) {
if (mCursor != null) {
mCursor.close();
}
mCursor = cursor;
notifyDataSetChanged();
}
}
My ClosetFragment, which loads the information on a Loader and to the fragments recyclerview.
package com.example.android.myshoecloset;
/*Assume appropriate imports*/
public class ClosetFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
private static final String TAG = "ClosetFragment";
protected RecyclerView mRecyclerView;
protected CustomAdapter mAdapter;
private static final int CUSTOM_LOADER_ID = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_closet, container, false);
rootView.setTag(TAG);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
mAdapter = new CustomAdapter(getActivity().getApplicationContext());
mRecyclerView.setAdapter(mAdapter);
getActivity().getSupportLoaderManager().initLoader(CUSTOM_LOADER_ID, null, this);
return rootView;
}
#Override
public void onResume()
{
super.onResume();
getActivity().getSupportLoaderManager().restartLoader(CUSTOM_LOADER_ID, null, this); }
#Override
public Loader<Cursor> onCreateLoader(int id, final Bundle loaderArgs) {
return new AsyncTaskLoader<Cursor>(getActivity().getApplicationContext()) {
Cursor mTaskData = null;
#Override
protected void onStartLoading()
{
if(mTaskData != null)
{
deliverResult(mTaskData);
}
else
{
forceLoad();
}
}
public Cursor loadInBackground()
{
try
{
return getActivity().getApplicationContext().getContentResolver().query(DatabaseContract.CONTENT_URI,
null,
null,
null,
null);
} catch(Exception e)
{
Log.e("", "Failed to asynchronously load data.");
e.printStackTrace();
return null;
}
}
public void deliverResult(Cursor data)
{
mTaskData = data;
super.deliverResult(data);
}
};
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data)
{
mAdapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader)
{
mAdapter.swapCursor(null);
}
}
Finally here is my DetailsActivity(when the recyclerview item is clicked this is where the click will take you)
package com.example.android.myshoecloset;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.android.myshoecloset.data.CustomAdapter;
public class ShoeDetailActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shoe_detail);
ImageView imgShoe = (ImageView) findViewById(R.id.shoeImgDetails);
TextView brandShoe = (TextView) findViewById(R.id.shoeBrandDetails);
TextView nameShoe = (TextView) findViewById(R.id.shoeNameDetails);
byte[] b = getIntent().getByteArrayExtra("ImageBit");
Bitmap bmp = BitmapFactory.decodeByteArray(b, 0, b.length);
imgShoe.setImageBitmap(bmp);
brandShoe.setText(getIntent().getStringExtra("ShoeName"));
nameShoe.setText(getIntent().getStringExtra("BrandName"));
}
}
Thanks!
As far as I can tell, the relevant pieces of your code are the onClick method in your view holder:
#Override
public void onClick(View v) {
Intent i = new Intent(v.getContext(), ShoeDetailActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
v.getContext().startActivity(i);
}
And the onCreate method in your details activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
byte[] b = getIntent().getByteArrayExtra("ImageBit");
...
brandShoe.setText(getIntent().getStringExtra("ShoeName"));
nameShoe.setText(getIntent().getStringExtra("BrandName"));
}
In the details activity, you're trying to pull information out of the intent extras... but you've never provided that information in the first place. Making this information available to your view holder will require re-thinking how you've implemented the view holder itself.
I believe you should be able to use the viewholder's "adapter position" to get the necessary info out of your cursor at click time. Maybe something like this:
#Override
public void onClick(View v) {
int position = getAdapterPosition();
mCursor.moveToPosition(position);
Intent i = new Intent(v.getContext(), ShoeDetailActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
int imgValue = mCursor.getColumnIndex(DatabaseContract.ShoeColumns.SHOE_IMAGE);
int shoeBrandName = mCursor.getColumnIndex(DatabaseContract.ShoeColumns.SHOE_BRAND);
int shoeName = mCursor.getColumnIndex(DatabaseContract.ShoeColumns.SHOE_NAME);
i.putExtra("ImageBit", mCursor.getBlob(imgValue));
i.putExtra("ShoeName", mCursor.getString(shoeBrandName));
i.putExtra("BrandName", mCursor.getString(shoeName));
v.getContext().startActivity(i);
}
(Note that "ShoeName" and "BrandName" appear to be swapped, but they're also swapped in your details activity so I left them that way.)
If this getAdapterPosition() + mCursor method doesn't work for you, you can always pass the necessary information to the view holder at bind time, and update the onClick() method when binding.
Let me know if this works for you. If it doesn't, we can try to figure it out from here.
I'm trying to visualize a toast inside a fragment by pressing an item of a recycling but I can not see it
Note: There is no error in the log attached to my class
This is my fragment
public class FotoFragment extends Fragment
{
private Cursor cursor;
private int columnIndex;
private static final String TAG = "RecyclerViewExample";
private List<DataPictures> mediaList = new ArrayList<>();
private RecyclerView mRecyclerView;
private MediaRVAdapter adapter;
String type = "";
public FotoFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
type = "images";
new MediaAsyncTask().execute(type);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_blank, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 3));
return view;
}
public class MediaAsyncTask extends AsyncTask<String, Void, Integer> {
#Override
protected Integer doInBackground(String... params) {
Integer result = 0;
String type = params[0];
try {
mediaList = new ArrayList<>();
if (type.equalsIgnoreCase("images")) {
result = 1;
}
} catch (Exception e) {
e.printStackTrace();
result = 0;
}
return result;
}
#Override
protected void onPostExecute(Integer result) {
if (result == 1) {
adapter = new MediaRVAdapter(getActivity(), mediaList);
mRecyclerView.setAdapter(adapter);
mRecyclerView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getActivity(), "Click pressed",Toast.LENGTH_SHORT).show();
}
});
} else {
Log.e(TAG, "Failed to show list");
}
}
}
}
This is my adapter
public class MediaRVAdapter extends RecyclerView.Adapter<MediaListRowHolder> {
private List<DataPictures> itemList;
private Context mContext;
public MediaRVAdapter(Context context, List<DataPictures> itemList) {
this.itemList = itemList;
this.mContext = context;
}
#Override
public MediaListRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_row, null);
MediaListRowHolder mh = new MediaListRowHolder(v);
return mh;
}
#Override
public void onBindViewHolder(MediaListRowHolder mediaListRowHolder, int i) {
try{
DataPictures item = itemList.get(i);
Uri uri = Uri.fromFile(new File(item.getFilePath()));
if(item.getFileType().equalsIgnoreCase("video")) {
Bitmap bmThumbnail = ThumbnailUtils.
extractThumbnail(ThumbnailUtils.createVideoThumbnail(item.getFilePath(),
MediaStore.Video.Thumbnails.FULL_SCREEN_KIND), 90, 60);
if(bmThumbnail != null) {
mediaListRowHolder.thumbnail.setImageBitmap(bmThumbnail);
}
} else if (item.getFileType().equalsIgnoreCase("audio")) {
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
mmr.setDataSource(item.getFilePath());
try{
if (mmr != null) {
byte[] art = mmr.getEmbeddedPicture();
Bitmap bmp = BitmapFactory.decodeByteArray(art,0,art.length);
if(bmp != null) {
bmp= ThumbnailUtils.extractThumbnail(bmp,90,60);
mediaListRowHolder.thumbnail.setImageBitmap(bmp);
}
}
}catch (Exception e){
e.printStackTrace();
}
}else {
Picasso.with(mContext).load(uri)
.error(R.drawable.logo_slogan)
.placeholder(R.drawable.logo_slogan)
.centerCrop()
.resize(90, 60)
.into(mediaListRowHolder.thumbnail);
}
}catch (Exception e) {
e.printStackTrace();
}
}
#Override
public int getItemCount() {
return (null != itemList ? itemList.size() : 0);
}
}
Adapter class adapter
public class MediaListRowHolder extends RecyclerView.ViewHolder {
protected ImageView thumbnail;
protected TextView title;
public MediaListRowHolder(View view) {
super(view);
this.thumbnail = (ImageView) view.findViewById(R.id.thumbnail);
this.title = (TextView) view.findViewById(R.id.title);
}
}
solution:
public class MediaListRowHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
protected ImageView thumbnail;
protected TextView title;
public MediaListRowHolder(View view) {
super(view);
this.thumbnail = (ImageView) view.findViewById(R.id.thumbnail);
this.title = (TextView) view.findViewById(R.id.title);
view.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "position = " + getPosition(), Toast.LENGTH_SHORT).show();
}
}
I think you can do this, such as the following code:
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
/**
* Author:Administrator on 2016/9/2 0002 20:37
* Contact:289168296#qq.com
*/
public abstract class OnItemSelectedListener implements RecyclerView.OnItemTouchListener{
private final GestureDetector mGestureDetector;
public OnItemSelectedListener(Context context){
mGestureDetector = new GestureDetector(context,
new GestureDetector.SimpleOnGestureListener(){
#Override public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
}
public abstract void onItemSelected(RecyclerView.ViewHolder holder, int position);
#Override public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
if (mGestureDetector.onTouchEvent(e)) {
View touchedView = rv.findChildViewUnder(e.getX(), e.getY());
onItemSelected(rv.findContainingViewHolder(touchedView),
rv.getChildAdapterPosition(touchedView));
}
return false;
}
#Override public void onTouchEvent(RecyclerView rv, MotionEvent e) {
throw new UnsupportedOperationException("Not implemented");
}
#Override public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
throw new UnsupportedOperationException("Not implemented");
}
}
And then to the RecycleView registration event, the event can be handled:
private RecyclerView grid;
grid.setAdapter(new PhotoAdapter(this, relevantPhotos));
grid.addOnItemTouchListener(new OnItemSelectedListener(MainActivity.this) {
#Override public void onItemSelected(RecyclerView.ViewHolder holder, int position) {
if (!(holder instanceof PhotoViewHolder)) {
return;
}
PhotoItemBinding binding = ((PhotoViewHolder) holder).getBinding();
final Intent intent = getDetailActivityStartIntent(MainActivity.this, relevantPhotos, position, binding);
final ActivityOptions activityOptions = getActivityOptions(binding);
MainActivity.this.startActivityForResult(intent, IntentUtil.REQUEST_CODE,
activityOptions.toBundle());
}
});
PhotoAdapter.java:
import android.content.Context;
import android.databinding.DataBindingUtil;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import com.bumptech.glide.Glide;
import com.googlesamples.unsplash.R;
import com.googlesamples.unsplash.data.model.Photo;
import com.googlesamples.unsplash.databinding.PhotoItemBinding;
import com.googlesamples.unsplash.ui.ImageSize;
import java.util.ArrayList;
public class PhotoAdapter extends RecyclerView.Adapter<PhotoViewHolder> {
private final ArrayList<Photo> photos;
private final int requestedPhotoWidth;
private final LayoutInflater layoutInflater;
public PhotoAdapter(#NonNull Context context, #NonNull ArrayList<Photo> photos) {
this.photos = photos;
requestedPhotoWidth = context.getResources().getDisplayMetrics().widthPixels;
layoutInflater = LayoutInflater.from(context);
}
#Override
public PhotoViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
return new PhotoViewHolder((PhotoItemBinding) DataBindingUtil.inflate(layoutInflater,
R.layout.photo_item, parent, false));
}
#Override
public void onBindViewHolder(final PhotoViewHolder holder, final int position) {
PhotoItemBinding binding = holder.getBinding();
Photo data = photos.get(position);
binding.setData(data);
binding.executePendingBindings();
Glide.with(layoutInflater.getContext())
.load(holder.getBinding().getData().getPhotoUrl(requestedPhotoWidth))
.placeholder(R.color.placeholder)
.override(ImageSize.NORMAL[0], ImageSize.NORMAL[1])
.into(holder.getBinding().photo);
}
#Override
public int getItemCount() {
return photos.size();
}
#Override
public long getItemId(int position) {
return photos.get(position).id;
}
}