How to pass ArrayList from Adapter to activity? - android

I need send ArrayList list_add to activity but I don't know how I can do it if is possible share it on main activity for use it in the future.
Anyone can help me to implement a method for do it?
below have MainAdatper for recyclerview where I have a list_add and want passed it to main activity and after I can add it to
class MainAdapter extends RecyclerView.Adapter <MainAdapter.ViewHolder> {
private static int lastCheckedPos = 0;
ArrayList<String> list_add = new ArrayList<>();
ArrayList<String> lista_show;
private Context context;
String t;
public MainAdapter(ArrayList<String> lista_shows, Context context) {
lista_show = lista_shows;
}
#Override
public MainAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from (parent.getContext ()).inflate (R.layout.row,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final MainAdapter.ViewHolder holder, final int position) {
holder.mdevice.setText (lista_show.get (position));
holder.cardView.setOnLongClickListener (new View.OnLongClickListener () {
#Override
public boolean onLongClick(View v) {
t = lista_show.get(position);
if (list_add.contains(t)) {
Toast.makeText(v.getContext (), t+"Already Selected", Toast.LENGTH_SHORT).show();
} else {
list_add.add(t);
holder.cardView.setCardBackgroundColor(Color.parseColor("#60B5EC"));
Toast.makeText(v.getContext (), t+"Added", Toast.LENGTH_SHORT).show();
}
return true;
}
});
holder.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
t = lista_show.get (position);
holder.cardView.setCardBackgroundColor(Color.WHITE);
if (! list_add.contains(t)) {
Toast.makeText(v.getContext (), "Long press for add", Toast.LENGTH_SHORT).show();
} else {
list_add.remove(t);
Toast.makeText(v.getContext (), t+"Removed", Toast.LENGTH_SHORT).show();
}
}
});
}
#Override
public int getItemCount() {
return lista_show.size ();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView mdevice;
CardView cardView;
public ViewHolder( View itemView) {
super (itemView);
mdevice = itemView.findViewById (R.id.device);
cardView = itemView.findViewById (R.id.mcardview);
}
}
}

Add interface for callback:
public interface ListOwner {
void push(ArrayList<String> list);
}
Set refernce in adapter:
private ListOwner listOwner;
public MainAdapter(ArrayList<String> lista_shows, Context context, ListOwner owner) {
this.lista_show = lista_shows;
this.listOwner = owner;
}
The call it in adapter when you need:
if (listOwner != null) {
listOwner.push(list_add);
}
Of course, implement ListOwner by your activity:
public class MyActivity extends AppCompatActivity implements ListOwner {
// all code
// create instance of adapter:
mAdapter = new MainAdapter(list_show, MyActivity.this, MyActivity.this);
#Override
public void push(ArrayList<String> list) {
// you have the list here
}
}
P.S.
You can omit interface and pass reference to the Activity directly (MyActivity in the sample)

Related

Hide the visibility of the nested recyclerview in android on ChildItem Click

I have a nested recycler view on which child item click I want the whole child recycler view to set visibility GONE.
I have tried some way to do it. But keeps on loosing the recycler view state and wrong data show's up. Help, please.
Here is ParentAdapter.java code
public class MessageListAdapter extends RecyclerView.Adapter {
private Context mContext;
private static final int VIEW_TYPE_MESSAGE_SENT = 1;
private static final int VIEW_TYPE_MESSAGE_RECEIVED = 2;
private List<Payload> chatMessageList;
private RecyclerView.RecycledViewPool recycledViewPool;
private OnItemClickListener onItemClickListener;
MessageListAdapter(Context context, List<Payload> chatMessageList, OnItemClickListener onItemClickListener) {
this.mContext = context;
this.chatMessageList = chatMessageList;
this.onItemClickListener = onItemClickListener;
recycledViewPool = new RecyclerView.RecycledViewPool();
}
#Override
public int getItemCount() {
return chatMessageList.size();
}
// Determines the appropriate ViewType according to the sender of the message.
#Override
public int getItemViewType(int position) {
Payload message = chatMessageList.get(position);
if (TextUtils.equals(message.getUserType(), "USER")) {
// If the current user is the sender of the message
return VIEW_TYPE_MESSAGE_SENT;
} else {
// If some other user sent the message
return VIEW_TYPE_MESSAGE_RECEIVED;
}
}
// Inflates the appropriate layout according to the ViewType.
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view;
if (viewType == VIEW_TYPE_MESSAGE_SENT) {
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_user_msg, parent, false);
return new SentMessageHolder(view);
} else {
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_bot_msg, parent, false);
return new ReceivedMessageHolder(view);
}
}
// Passes the message object to a ViewHolder so that the contents can be bound to UI.
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Payload chatMessage = chatMessageList.get(position);
switch (holder.getItemViewType()) {
case VIEW_TYPE_MESSAGE_SENT:
((SentMessageHolder) holder).bind(chatMessage.getMessage(), getFormattedTime());
break;
case VIEW_TYPE_MESSAGE_RECEIVED:
((ReceivedMessageHolder) holder).bind(chatMessage.getMessage(), getFormattedTime());
((ReceivedMessageHolder) holder).bindRv(chatMessage, mContext, recycledViewPool, onItemClickListener);
break;
}
}
private static class SentMessageHolder extends RecyclerView.ViewHolder {
TextView txtViewChatMsgUser;
TextView txtViewDateTimeUser;
SentMessageHolder(View itemView) {
super(itemView);
txtViewChatMsgUser = itemView.findViewById(R.id.txtViewChatMsgUser);
txtViewDateTimeUser = itemView.findViewById(R.id.txtViewDateTimeUser);
}
void bind(String message, String time) {
txtViewChatMsgUser.setText(message);
txtViewDateTimeUser.setText(time);
}
}
private class ReceivedMessageHolder extends RecyclerView.ViewHolder {
TextView txtViewChatMsgBot;
RecyclerView rvDeepLink;
TextView txtViewDateTimeBot;
ReceivedMessageHolder(View itemView) {
super(itemView);
txtViewChatMsgBot = itemView.findViewById(R.id.txtViewChatMsgBot);
rvDeepLink = itemView.findViewById(R.id.itemRvDeepLink);
txtViewDateTimeBot = itemView.findViewById(R.id.txtViewDateTimeBot);
}
void bind(String message, String time) {
txtViewChatMsgBot.setText(message);
txtViewDateTimeBot.setText(time);
}
void bindRv(Payload chatMessage, Context context, RecyclerView.RecycledViewPool recycledViewPool, OnItemClickListener onItemClickListener) {
if (chatMessage.getData() != null && !chatMessage.isOptionSelected()) {
DeepLinkAdapter deepLinkAdapter = new DeepLinkAdapter(context, chatMessage.getData(), onItemClickListener, getAdapterPosition());
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context);
linearLayoutManager.setOrientation(RecyclerView.VERTICAL);
rvDeepLink.setLayoutManager(linearLayoutManager);
rvDeepLink.setAdapter(deepLinkAdapter);
rvDeepLink.setRecycledViewPool(recycledViewPool);
deepLinkAdapter.notifyDataSetChanged();
} else {
rvDeepLink.setVisibility(View.GONE);
}
}
}
private String getFormattedTime() {
SimpleDateFormat dateFormat = new SimpleDateFormat("hh.mm aa", Locale.ENGLISH);
return dateFormat.format(new Date());
}
public void clearData() {
chatMessageList.clear();
notifyDataSetChanged();
}
public void onSelected(int position) {
chatMessageList.get(position).setOptionSelected(true);
notifyItemChanged(position);
}
}
Here is my ChildAdapter.java code:
public class DeepLinkAdapter extends RecyclerView.Adapter<DeepLinkAdapter.DeepLinkViewHolder> {
private List<DataItem> dataItemList;
private Context context;
private OnItemClickListener onItemClickListener;
private int parentPos;
DeepLinkAdapter(Context context, List<DataItem> dataItemList, OnItemClickListener onItemClickListener, int parentPos) {
this.context = context;
this.dataItemList = dataItemList;
this.onItemClickListener = onItemClickListener;
this.parentPos = parentPos;
}
#NonNull
#Override
public DeepLinkViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new DeepLinkViewHolder(LayoutInflater.from(context).inflate(R.layout.inner_bot_msg, parent, false), onItemClickListener, parentPos);
}
#Override
public void onBindViewHolder(#NonNull final DeepLinkViewHolder holder, final int position) {
DataItem dataItem = dataItemList.get(position);
if (TextUtils.isEmpty(dataItem.getDeeplink())) {
holder.deepLinkText.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
} else {
holder.deepLinkText.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_right_arrow, 0);
}
if (!TextUtils.isEmpty(dataItem.getText())) {
holder.deepLinkText.setVisibility(View.VISIBLE);
holder.deepLinkText.setText(dataItem.getText());
} else {
holder.deepLinkText.setVisibility(View.GONE);
}
}
#Override
public int getItemCount() {
if (dataItemList != null) {
return dataItemList.size();
} else {
return 0;
}
}
class DeepLinkViewHolder extends RecyclerView.ViewHolder {
private TextView deepLinkText;
DeepLinkViewHolder(View itemView, OnItemClickListener onItemClickListener, int parentPos) {
super(itemView);
deepLinkText = itemView.findViewById(R.id.innerDeepLinkMsgText);
if (onItemClickListener != null) {
deepLinkText.setOnClickListener(v -> {
onItemClickListener.onItemClick(getAdapterPosition(), parentPos);
});
}
}
}
}
Here is my Click Listener Code in the Activity:
#Override
public void onItemClick(int childPos, int parentPos) {
if (TextUtils.isEmpty(chatMessageList.get(parentPos).getData().get(childPos).getDeeplink())) {
String message = chatMessageList.get(parentPos).getData().get(childPos).getText();
if (!viewModel.sendMessage(message)) {
setMessage(getString(R.string.error_something_went_wrong), ChatBotManager.UserType.BOT.toString());
} else {
messageListAdapter.onSelected(parentPos);
setMessage(message, ChatBotManager.UserType.USER.toString());
}
} else {
if (TextUtils.equals(chatMessageList.get(parentPos).getData().get(childPos).getDeeplink(), "restart")) {
if (messageListAdapter != null) {
messageListAdapter.clearData();
viewModel.sendMessage("start");
}
} else {
String uri = chatMessageList.get(parentPos).getData().get(childPos).getDeeplink();
Intent newIntent = new Intent(ApplicationClass.getContext(), TalkLinkingActivity.class);
newIntent.setData(Uri.parse(uri));
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newIntent);
finish();
}
}
}
Please help what I am missing here, My goal is to have a click listener from the child adapter on Activity, and also after the click on the item, I want to remove the whole recycler view. Just like a chatbot in Swiggy.
Have a method in DeepLinkAdapter that clears the whole list:
public class DeepLinkAdapter extends RecyclerView.Adapter<DeepLinkAdapter.DeepLinkViewHolder> {
.......
public void clearTheWholeList(){
dataItemList.clear();
notifyDataSetChanged();
}
}
Have a method in your MessageListAdapter that removes an item completely:
public class MessageListAdapter extends RecyclerView.Adapter {
......
......
private int positionToClear = -1;
public void removeItem(int position){
positionToClear = position;
notifyDataSetChanged();
}
//in onBindViewHolder
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
............
............
//pass the positionToClear here
((ReceivedMessageHolder) holder).bindRv(chatMessage, mContext, recycledViewPool, onItemClickListener , positionToClear);
}
.......
}
In ReceivedMessageHolder
private class ReceivedMessageHolder extends RecyclerView.ViewHolder {
//here add new param for removed position
void bindRv(Payload chatMessage, Context context, RecyclerView.RecycledViewPool recycledViewPool, OnItemClickListener onItemClickListener, int positionToClear) {
if (chatMessage.getData() != null && !chatMessage.isOptionSelected()) {
DeepLinkAdapter deepLinkAdapter = new DeepLinkAdapter(context, chatMessage.getData(), onItemClickListener, getAdapterPosition());
//do a check here
if(getAdapterPosition() == positionToClear){
deepLinkAdapter.clearTheWholeList();
}
.......
.......
.......
} else {
rvDeepLink.setVisibility(View.GONE);
}
}
}
Assuming the onItemClick interface is working:
#Override
public void onItemClick(int childPos, int parentPos) {
...........
...........
//somewhere where you want the item to be removed
messageListAdapter.removeItem(parentPos);
............
............
}

How to submit a click event on a button inside an item in a recylcerview while respecting MVVM architecture?

I am having a problem, it is technical and conceptual, I am trying to use MVVM architecture and I don't want to drive away from it, so I have a list of items, each item has a delete button, I show the list using recylcerview, so I am using an adapter, now when I call an event on each row I do this :
This is my Adapter, go to deleteBtn inside the ViewHolder.
public class ContractListAdapter extends RecyclerView.Adapter<ContractListAdapter.ContractViewHolder> {
List<ContractModel> contracts;
Context context;
public ContractListAdapter(Context context, List<ContractModel> contracts){
this.context = context;
this.contracts = contracts;
}
#NonNull
#Override
public ContractViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
ContratBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.contrat, parent, false); // ContratBinding >> as your list item layout named "contrat"
return new ContractViewHolder(binding);
}
#Override
public void onBindViewHolder(#NonNull ContractViewHolder holder, int position) {
holder.binding.setContract(contracts.get(position));
}
#Override
public int getItemCount() {
return this.contracts.size();
}
public class ContractViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
ContractsListViewModel listViewModel;
#BindView(R.id.courtier)
TextView courtier;
#BindView(R.id.delete)
Button deleteButton;
ContratBinding binding;
#BindView(R.id.contratImage)
ImageView contractImage;
public ContractViewHolder(#NonNull ContratBinding binding){
super(binding.getRoot());
this.binding = binding;
ButterKnife.bind(this, itemView);
itemView.setOnClickListener(this);
courtier.setOnClickListener(this);
deleteButton.setOnClickListener(this);
contractImage.setOnClickListener(this);
}
#Override
public void onClick(View v) {
int position = getAdapterPosition();
int idOfContract = contracts.get(position).getId();
if(deleteButton.getId() == v.getId()){
// action here
}
else {
Intent myIntent = new Intent(context, ContractActivity.class);
myIntent.putExtra("key", idOfContract + ""); //Optional parameters
context.startActivity(myIntent);
}
}
}
}
This is my MainActivity :
public class MainActivity extends AppCompatActivity {
ContractsListViewModel contractsListViewModel;
#BindView(R.id.contractList)
RecyclerView contractList;
#BindView(R.id.newContractBtn)
Button newContractBtn;
#BindView(R.id.listLoading)
ProgressBar listLoading;
#BindView(R.id.listError)
TextView listError;
RecyclerView.Adapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding main = DataBindingUtil.setContentView(this, R.layout.activity_main);
ButterKnife.bind(this);
main.contractList.setLayoutManager(new LinearLayoutManager(this));
contractsListViewModel = ViewModelProviders.of(this).get(ContractsListViewModel.class);
contractsListViewModel.call();
contractsListViewModel.contractList.observe(this,contractModels -> {
if(contractModels != null){
contractList.setVisibility((View.VISIBLE));
adapter = new ContractListAdapter(MainActivity.this, contractModels);
main.contractList.setAdapter(adapter);
}
});
contractsListViewModel.isLoading.observe(this,isLoading -> {
if(isLoading != null){
listLoading.setVisibility(isLoading ? View.VISIBLE : View.GONE );
if(isLoading){
listError.setVisibility(View.GONE);
contractList.setVisibility((View.GONE));
}
}
});
contractsListViewModel.error.observe(this,Error -> {
if(Error != null){
listError.setVisibility(Error ? View.VISIBLE : View.GONE );
}
});
newContractBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent newContractIntent = new Intent(getApplicationContext(), NewContractActivity.class);
MainActivity.this.startActivity(newContractIntent);
}
});
}
#Override
public void onResume()
{
super.onResume();
contractsListViewModel = ViewModelProviders.of(this).get(ContractsListViewModel.class);
contractsListViewModel.call();
}
}
So when I call an action and observe it I usually do in my MainActivity because I was instanciating my ListViewModel inside the MainActivity, and calling my ViewModel methods, but now I feel like I have to instantiate the same ViewModels in this ViewHolder.
First I don't know how, because when I call 'this' in my MainActivity it refers to MainActvity but If I call it in the ViewHolder ( not an activity ), it won't works, so how will I call my ViewModel in the ViewHolder.
contractsListViewModel = ViewModelProviders.of(this).get(ContractsListViewModel.class);
Second and it is more important, Am I respecting the MVVM architecture if I do this ?
Because how I am conceptualizing it :
#Override
public void onClick(View v) {
int position = getAdapterPosition();
int idOfContract = contracts.get(position).getId();
// Delete Button clicked
if(deleteButton.getId() == v.getId()){
// I call the ViewModel
// call the action I want ( delete request )
// observe it in my MainActivity
}
}
Any help would be much appreciated guys!
Thank you.
This is your updated Activity.
public class MainActivity extends AppCompatActivity {
ContractsListViewModel contractsListViewModel;
#BindView(R.id.contractList)
RecyclerView contractList;
#BindView(R.id.newContractBtn)
Button newContractBtn;
#BindView(R.id.listLoading)
ProgressBar listLoading;
#BindView(R.id.listError)
TextView listError;
RecyclerView.Adapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding main = DataBindingUtil.setContentView(this, R.layout.activity_main);
ButterKnife.bind(this);
main.contractList.setLayoutManager(new LinearLayoutManager(this));
contractsListViewModel = ViewModelProviders.of(this).get(ContractsListViewModel.class);
contractsListViewModel.call();
contractsListViewModel.contractList.observe(this,contractModels -> {
if(contractModels != null){
contracts.addAll(contractModels);
contractList.setVisibility((View.VISIBLE));
adapter = new ContractListAdapter(MainActivity.this, contractModels, new ContractListAdapter.OnButtonPressed() {
#Override
public void onClicked(int position) {
contractsListViewModel.callDelete(position);
}
});
main.contractList.setAdapter(adapter);
}
});
contractsListViewModel.isLoading.observe(this,isLoading -> {
if(isLoading != null){
listLoading.setVisibility(isLoading ? View.VISIBLE : View.GONE );
if(isLoading){
listError.setVisibility(View.GONE);
contractList.setVisibility((View.GONE));
}
}
});
contractsListViewModel.error.observe(this,Error -> {
if(Error != null){
listError.setVisibility(Error ? View.VISIBLE : View.GONE );
}
});
newContractBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent newContractIntent = new Intent(getApplicationContext(), NewContractActivity.class);
MainActivity.this.startActivity(newContractIntent);
}
});
}
#Override
public void onResume()
{
super.onResume();
contractsListViewModel = ViewModelProviders.of(this).get(ContractsListViewModel.class);
contractsListViewModel.call();
}
}
This is your updated ContractListAdapter
public class ContractListAdapter extends RecyclerView.Adapter<ContractListAdapter.ContractViewHolder> {
List<ContractModel> contracts;
Context context;
OnButtonPressed onButtonPressed;
public ContractListAdapter(Context context, List<ContractModel> contracts,OnButtonPressed onButtonPressed) {
this.context = context;
this.contracts = contracts;
this.onButtonPressed = onButtonPressed;
}
#NonNull
#Override
public ContractViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
ContratBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.contrat, parent, false); // ContratBinding >> as your list item layout named "contrat"
return new ContractViewHolder(binding);
}
#Override
public void onBindViewHolder(#NonNull ContractViewHolder holder, int position) {
holder.binding.setContract(contracts.get(position));
}
#Override
public int getItemCount() {
return this.contracts.size();
}
public class ContractViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
ContractsListViewModel listViewModel;
#BindView(R.id.courtier)
TextView courtier;
#BindView(R.id.delete)
Button deleteButton;
ContratBinding binding;
#BindView(R.id.contratImage)
ImageView contractImage;
public ContractViewHolder(#NonNull ContratBinding binding) {
super(binding.getRoot());
this.binding = binding;
ButterKnife.bind(this, itemView);
itemView.setOnClickListener(this);
courtier.setOnClickListener(this);
deleteButton.setOnClickListener(this);
contractImage.setOnClickListener(this);
}
#Override
public void onClick(View v) {
int position = getAdapterPosition();
int idOfContract = contracts.get(position).getId();
if (deleteButton.getId() == v.getId()) {
// action here
onButtonPressed.onClicked(position);
} else {
Intent myIntent = new Intent(context, ContractActivity.class);
myIntent.putExtra("key", idOfContract + ""); //Optional parameters
context.startActivity(myIntent);
}
}
}
interface OnButtonPressed {
void onClicked(int position);
}
}
You have to use binding adapter for your button clicks in MVVM architecture with data binding.All your button clicks will be in the same class.
<android.support.design.widget.Button
...
android:onClick="#{handlers::ButtonClicked}" />
public class MyClickHandlers {
public void onButtonClicked(View view) {
Toast.makeText(getApplicationContext(), "button clicked!", Toast.LENGTH_SHORT).show();
}
}
I would create a callback function in Activity and let Activity implement it:
interface OnDeleteClicklistener {
void onDelete(int id)
}
Then the activity would call its ViewModel inside this method:
void onDelete(int id) {
viewModel.deleteItem(id)
}
Then instead of passing the ViewModel to the Adapter, I would pass the activity as the interface:
recyclerView.setAdapter(MyAdapter(this, listOfItems)
Adapter constructor:
MyAdapter(OnDeleteClicklistener listener, List<Item> list)

Why adnroidx recycler-view click not working when click it's item?

I'm trying to implement RecyclerView onclick listener, but it is not working. I've tried a lot, and try to implement other way too, but not working at all.
My Main Class:
public class MainMenuDashboard extends AppCompatActivity{
private RecyclerView recyclerMenu;
private RecyclerViewMenuAdapter menuAdapter;
private Call<CategoryModel> categoryModelCall;
private TokenManager tokenManagerMainMenu;
private ApiService serviceMainMenu;
List<CategoryModel.Subset> menuList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_menu_dashboard);
tokenManagerMainMenu = TokenManager.getInstance(getSharedPreferences("prefs", MODE_PRIVATE));
serviceMainMenu = RetrofitBuilder.createServiceWithAuth(ApiService.class, tokenManagerMainMenu);
recyclerMenu = findViewById(R.id.recyclerMenu);
menuList = new ArrayList<>();
GridLayoutManager layoutManager = new GridLayoutManager(MainMenuDashboard.this, 2, GridLayoutManager.VERTICAL, false);
recyclerMenu.setLayoutManager(layoutManager);
menuAdapter = new RecyclerViewMenuAdapter(menuList);
recyclerMenu.setAdapter(menuAdapter);
menuAdapter.notifyDataSetChanged();
mainMenuDashBoardToolbar = findViewById(R.id.mainMenuDashBoardToolbar);
setSupportActionBar(mainMenuDashBoardToolbar);
menuContent();
}
private void menuContent() {
categoryModelCall = serviceMainMenu.menuContent(incomingRoleId, true);
categoryModelCall.enqueue(new Callback<CategoryModel>() {
#Override
public void onResponse(#NotNull Call<CategoryModel> call, #NotNull Response<CategoryModel> response) {
if (response.isSuccessful() && response.body() != null && response.code() != 400) {
//findViewById(R.id.shimmerCategory).setVisibility(View.GONE);
CategoryModel categoryModel = response.body();
menuList = categoryModel.getSubset();
menuAdapter = new RecyclerViewMenuAdapter(menuList);
recyclerMenu.setAdapter(menuAdapter);
//menuAdapter.notifyDataSetChanged();
menuAdapter.setOnItemClickListener(new RecyclerViewMenuAdapter.ClickListenerMenu() {
#Override
public void onClick(int position) {
Toast.makeText(MainMenuDashboard.this, "Position "+position+" Clicked", Toast.LENGTH_SHORT).show();
menuAdapter.notifyDataSetChanged();
}
});
menuAdapter.notifyDataSetChanged();
}else {
if (response.code() == 401) {
Intent i = new Intent(MainMenuDashboard.this, MainActivity.class);
i.putExtra("USER_SESSION", true);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
tokenManagerMainMenu.deleteToken();
startActivity(i);
finish();
}
}
}
#Override
public void onFailure(#NotNull Call<CategoryModel> call, #NotNull Throwable t) {
}
});
}
}
My Adapter:
public class RecyclerViewMenuAdapter extends RecyclerView.Adapter<RecyclerViewMenuAdapter.RecyclerViewHolder> {
private static final String TAG = "NotesRecyclerAdapter";
private List<CategoryModel.Subset> subsetsCategories;
private ClickListenerMenu mClickListener;
private Context context;
public RecyclerViewMenuAdapter(List<CategoryModel.Subset> subsetsCategories) {
this.subsetsCategories = subsetsCategories;
}
#NonNull
#Override
public RecyclerViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycler_main_menu_category, parent, false);
return new RecyclerViewHolder(view, mClickListener);
}
#Override
public void onBindViewHolder(#NonNull final RecyclerViewHolder viewHolder, final int position) {
String menuCategoryImage = subsetsCategories.get(position).getIcon();
Picasso.get().load(menuCategoryImage).placeholder(R.drawable.admin).into(viewHolder.menuThumb);
String menuCategoryName = subsetsCategories.get(position).getName();
viewHolder.menuName.setText(menuCategoryName);
//Item click
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
mClickListener.onClick(position);
//Toast.makeText(context, "Position "+position+" Clicked", Toast.LENGTH_SHORT).show();
notifyDataSetChanged();
}
});
}
#Override
public int getItemCount() {
return subsetsCategories.size();
}
public static class RecyclerViewHolder extends RecyclerView.ViewHolder{
ImageView menuThumb;
TextView menuName;
private ClickListenerMenu mListener;
//ClickListenerMenu clickListenerMenu;
public RecyclerViewHolder(View view, ClickListenerMenu clickListenerMenu) {
super(view);
menuThumb = view.findViewById(R.id.menuThumb);
menuName = view.findViewById(R.id.menuName);
mListener = clickListenerMenu;
}
}
public void setOnItemClickListener(ClickListenerMenu clickListener) {
mClickListener = clickListener;
}
public interface ClickListenerMenu {
void onClick(int position);
}
}
I still can't find where I did wrong!! Any insight will be very appreciated
Thank You
Add item click listener in your adapter.
#Override
public void onBindViewHolder(#NonNull RecyclerViewHolder viewHolder, int position) {
String menuCategoryImage = subsetsCategories.get(position).getIcon();
Picasso.get().load(menuCategoryImage).placeholder(R.drawable.admin).into(viewHolder.menuThumb);
String menuCategoryName = subsetsCategories.get(position).getName();
viewHolder.menuName.setText(menuCategoryName);
//Item click
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
// Do something
}
});
}
Initialise your recycler view outside and put this line menuAdapter.notifyDataSetChanged(); where you add data in your list.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_menu_dashboard);
tokenManagerMainMenu = TokenManager.getInstance(getSharedPreferences("prefs", MODE_PRIVATE));
serviceMainMenu = RetrofitBuilder.createServiceWithAuth(ApiService.class, tokenManagerMainMenu);
recyclerMenu = findViewById(R.id.recyclerMenu);
menuList = new List<CategoryModel.Subset>();
GridLayoutManager layoutManager = new GridLayoutManager(MainMenuDashboard.this, 2, GridLayoutManager.VERTICAL, false);
recyclerMenu.setLayoutManager(layoutManager);
menuAdapter = new RecyclerViewMenuAdapter(menuList);
recyclerMenu.setAdapter(menuAdapter);
menuAdapter.notifyDataSetChanged();
menuContent();
}
I hope this can help you!
Add these line in the onBindViewHolder() method:
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//remove this lines
//mClickListener.onClick(position);
//notifyDataSetChanged();
//add this
context.startActivity(new Intent(context,SecondActivity.class))
}
});
and in your MainMenuDashboard class, initialize your Adapter like this:
menuAdapter = new RecyclerViewMenuAdapter(this,menuList);
also change your Adapter constructor like this:
public RecyclerViewMenuAdapter(Context context,List<CategoryModel.Subset> subsetsCategories) {
this.subsetsCategories = subsetsCategories;
this.context = context;
}
```

Android RecyclreView OnCLick Listener

Error on android recyclerView Adapter. App will stop working while click on RecyclerView items. I want to go other activity when click any items, when i'm using Toast it working fine but if i add Intent then it stop working.
Here is my Interface :
public interface OnItemClickListener {
void onClick(View view, int position);
}
here is my recycler Adapter calss :
public class RecAdapter extends RecyclerView.Adapter<RecAdapter.MyViewHolder> {
private List<Items> items;
private Context context;
public RecAdapter(List<Items> items, Context context )
{
this.items = items;
this.context = context;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_item,parent,false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.countryname.setText(items.get(position).getCountryname());
holder.rank.setText(items.get(position).getRank());
Picasso.with(context)
.load(items.get(position).getFlag())
.into(holder.flag);
holder.setClickListener(new OnItemClickListener() {
#Override
public void onClick(View view, int position) {
Intent intent = new Intent(context , Main2Activity.class);
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return items.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView countryname, rank;
ImageView flag;
private OnItemClickListener clickListener;
public MyViewHolder(View itemView) {
super(itemView);
countryname = (TextView) itemView.findViewById(R.id.capital);
rank = (TextView) itemView.findViewById(R.id.rank);
flag = (ImageView) itemView.findViewById(R.id.flag);
itemView.setTag(itemView);
itemView.setOnClickListener(this);
}
public void setClickListener(OnItemClickListener itemClickListener) {
this.clickListener = itemClickListener;
}
#Override
public void onClick(View view) {
if (clickListener != null) clickListener.onClick(view, getAdapterPosition());
}
}
}
Add click listener like this:-
View itemView;
Context context;
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_view, parent, false);
this.context=parent.getContext();
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context , Main2Activity.class);
context.startActivity(intent);
}
});
}
copying an answer of mine from a different question:
as you already know this method is no longer available in the RecyclerView class.
My approach towards implementing onClick events in a RecyclerView is something like this:
class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
interface OnClickListener {
void onClick(Item item);
}
private final List<Item> dataset;
private final OnClickListener l;
public MyAdapter(List<Item> data, OnClickListener listener) {
this.dataset = data;
this.l = listener;
}
#Override MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = //inflate layout
MyClick click = new MyClick() {
onClick(int position) {
if (l != null) {
l.onClick(dataset.get(position));
}
}
};
return new MyViewHolder(click, v);
}
static class MyViewHolder {
final MyClick l;
public MyViewHolder(MyClick listener, View view) {
super(view);
l = listener;
// inflate views
view.setOnClickListener(new OnClickListener() {
if (l != null) {
l.onClick(getAdapterPosition());
}
});
}
interface MyClick {
void onClick(int position);
}
}
}
class MyActivity extends AppCompatActivity {
#Override void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set layout
MyAdapter adapter = new MyAdapter(getData(), new OnClickListener() {
#Override onClick(Item item) {
// do stuff with item
}
});
}
}
You can not click an holder directly..... give a id to the view then re write the code as below:
holder.(someitem).setClickListener(new OnItemClickListener() {//you need a view to execute the onclicklistener
#Override
public void onClick(View view, int position) {
Intent intent = new Intent(context , Main2Activity.class);
context.startActivity(intent);
}
});
Here is code which i create click listener for Recycler Item Click
Using this you will get two types of click
Simple Item click.
Item Long click.
Here is RecyclerItemClickListener.java File
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
public interface OnItemClickListener
{
void onItemClick(View view, int position);
void onItemLongClick(View view, int position);
}
private OnItemClickListener mListener;
private GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener)
{
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener()
{
#Override
public boolean onSingleTapUp(MotionEvent e)
{
return true;
}
#Override
public void onLongPress(MotionEvent e)
{
View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());
if(childView != null && mListener != null)
{
mListener.onItemLongClick(childView, recyclerView.getChildPosition(childView));
}
}
});
}
#Override
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e)
{
View childView = view.findChildViewUnder(e.getX(), e.getY());
if(childView != null && mListener != null && mGestureDetector.onTouchEvent(e))
{
mListener.onItemClick(childView, view.getChildPosition(childView));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView view, MotionEvent motionEvent){}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
How to use in Activity and Fragment
rvcyclerView.addOnItemTouchListener(new RecyclerItemClickListener(context, rvcyclerView,
new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
//do you what you want tot do simple click
}
#Override
public void onItemLongClick(View view, int position) {
//do you what you want tot do on long click
}
}));
public class RecAdapter extends RecyclerView.Adapter<RecAdapter.MyViewHolder> implements View.OnClickListener {
private List<Items> items;
private Context context;
private OnItemClickListener clickListener;
public RecAdapter(List<Items> items, Context context )
{
this.items = items;
this.context = context;
}
public void setClickListener(OnItemClickListener itemClickListener) {
this.clickListener = itemClickListener;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_item,parent,false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.countryname.setText(items.get(position).getCountryname());
holder.rank.setText(items.get(position).getRank());
Picasso.with(context)
.load(items.get(position).getFlag())
.into(holder.flag);
holder.flag.setOnClickListener(this);
}
#Override
public int getItemCount() {
return items.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView countryname, rank;
ImageView flag;
public MyViewHolder(View itemView) {
super(itemView);
countryname = (TextView) itemView.findViewById(R.id.capital);
rank = (TextView) itemView.findViewById(R.id.rank);
flag = (ImageView) itemView.findViewById(R.id.flag);
}
#Override
public void onClick(View view) {
if (clickListener != null) clickListener.onClick(view, getAdapterPosition());
}
}
}
On Your Activity / Fragment Implement OnItemClickListener
public class MainActivity extends AppCompatActivity implements OnItemClickListener{
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayoutManager layout = new
LinearLayoutManager(getContext(),LinearLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(layout );
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
RecAdapter adapter = new RecAdapter(items ,getContext());
adapter.setClickListener(this);
mRecyclerView.setAdapter(adapter );
}
#Override
public void onClick(View view, int position) {
switch(view.getId()) {
}
}
}

Why is this custom listener null?

I am trying to create an interface between my Recyclerview Adapter and an Activity, so that when an item in the adapter is clicked, the Activity will react accordingly but the listener is always null.
Interface
public interface UrlTagCatClickedListener {
public void onUrlTagCatClicked (String chemicalURL);
}
Adapter
public class TagCatAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context mContext;
private List<TagCatItem> mTagCatItems;
private int lastPosition = -1;
private UrlTagCatClickedListener mTagCatClickedListener;
public TagCatAdapter(List<TagCatItem> tagCatItems, Context context) {
super();
this.mTagCatItems = tagCatItems;
this.mContext = context;
this.mTagCatClickedListener = null;
}
public void setTagCatClickedListener (UrlTagCatClickedListener tagCatClickedListener) {
this.mTagCatClickedListener = tagCatClickedListener;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.tag_cat_item, parent, false);
return new ItemViewHolder(v);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final TagCatItem tagCatItem = mTagCatItems.get(position);
((ItemViewHolder) holder).chemicalTitle.setText(Html.fromHtml(tagCatItem.getChemicalTitle()));
((ItemViewHolder) holder).chemicalDate.setText(tagCatItem.getChemicalDate());
((ItemViewHolder) holder).chemicalTitle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mTagCatClickedListener != null) { // mTagCatClickedListener is always null
mTagCatClickedListener.onUrlTagCatClicked(tagCatItem.getChemicalURL());
}
}
});
}
public class ItemViewHolder extends RecyclerView.ViewHolder{
public TextView chemicalTitle, chemicalDate;
public ItemViewHolder(final View mView) {
super(mView);
chemicalTitle = (TextView) mView.findViewById(R.id.tagcat_title);
chemicalDate = (TextView) mView.findViewById(R.id.tagcat_date);
}
}
#Override
public int getItemCount() {
return mTagCatItems.size();
}
}
Activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate called")
//Skipped a lot of codes that doesn't relate to the queation
List<TagCatItem> mTagCatItems = new ArrayList<>();
TagCatAdapter tagCatAdapter = new TagCatAdapter(mTagCatItems, this);
tagCatAdapter.setTagCatClickedListener(new UrlTagCatClickedListener() {
#Override
public void onUrlTagCatClicked(String chemicalURL) {
Log.d(TAG, "I go the url!!!!!!!!!! and it is + " + chemicalURL);
}
});
}
Please, do you have an idea why it's null and how I can fix it?
You have two different instances of TagCatAdapter in your given setup; one in the Activity, and one in the Fragment. You're setting the UrlTagCatClickedListener you've posted on the one created in the Activity, but it's the Fragment's TagCatAdapter instance that you're setting on the RecyclerView. That one doesn't have the listener set, so its mTagCatClickedListener is always null.
You just need to move the given UrlTagCatClickedListener to the TagCatAdapter in the Fragment, and remove the TagCatAdapter from the Activity, as you're not using that one anyway.

Categories

Resources