I Have a ListView in a Fragment, in my ListView's Item, i have a Button How can i call another Fragment a custom DialogFragment from clicking on the button and keep the item information?
you can Use interface ,
Create an Interface in Adapter class , then set it from owner fragment and when user click on Button call interface Method
Adapter class :
public class TestAdapter extends RecyclerView.Adapter<TestAdapter.ViewHolder> {
private ArrayList<AddressModel> dataset;
private WeakReference<Activity> activity;
private onChecked listener;
public TestAdapter(Activity activity, ArrayList<AddressModel> datasett) {
this.dataset = datasett;
this.activity = new WeakReference<Activity>(activity);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View rootView = LayoutInflater.from(activity.get()).inflate(R.layout.item_popup_change_address_step_two, null);
TextView tv = (TextView) rootView.findViewById(R.id.title_itemPopUp_ChangeAddress_TV);
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
tv.setBackground(ContextCompat.getDrawable(parent.getContext(), R.drawable.edittext_style));
RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
rootView.setLayoutParams(lp);
return new ViewHolder(rootView);
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.title.get().setText(dataset.get(position).getTitle());
holder.rootView.get().setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null) //call interface
listener.chekedListener(dataset.get(position));
}
});
}
#Override
public int getItemCount() {
if (dataset == null)
return 0;
return dataset.size();
}
public void setListener(onChecked listener) {
this.listener = listener;
}
public interface onChecked {
void chekedListener(AddressModel addressClass_serialized);
}
public class ViewHolder extends RecyclerView.ViewHolder {
private WeakReference<TextView> title;
private WeakReference<LinearLayout> rootView;
public ViewHolder(View itemView) {
super(itemView);
title = new WeakReference<TextView>((TextView) itemView.findViewById(R.id.title_itemPopUp_ChangeAddress_TV));
rootView = new WeakReference<LinearLayout>((LinearLayout) itemView.findViewById(R.id.rootCardView_addressItemPopUP_cd));
}
}
}
in fragment :
adapter.setListener(new TestAdapter.onChecked() {
#Override
public void chekedListener(AddressModel addressClass_serialized) {
//Call Dialog Here
}
});
Logic/Steps
Set the Click Listener in List Items.
Step 1:- Make Constructor in DialogFragment/CustomDialog to pass the Information from OnClick of ListItem.
Step 2:- Do whatevet u want in Dialog Class.
Related
I have a recycler view in my fragment and every recycler view row item has a button so when user clicks on a button it should open BottomSheetDialogFragment and detail info of that particular row item should be visible in BottomSheetDialogFragment.
What I did so far dialog fragment is showing properly on the click of a button but I am not getting any idea of how can I pass data to dialog fragment from adapter class.
Below is my code:
FactsAdapter.java
public class FactsAdapter extends RecyclerView.Adapter<FactsAdapter.ViewHolder> {
List<Facts> factList;
Context context;
public FactsAdapter(List<Facts> factList, Context context) {
this.factList = factList;
this.context = context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.facts_row,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
final Facts model = factList.get(position);
final String str1 = model.getDescription();
RequestOptions requestOptions = new RequestOptions();
requestOptions.placeholder(R.color.place);
holder.title.setText(model.getTitle());
Glide.with(context).load(model.getImage()).apply(requestOptions).into(holder.factImage);
holder.more.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
BottomSheet bottomSheet = new BottomSheet();
bottomSheet.show(((FragmentActivity) context).getSupportFragmentManager(),bottomSheet.getTag());
}
});
}
#Override
public int getItemCount() {
return factList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView factImage;
TextView title;
Button more;
public ViewHolder(#NonNull View itemView) {
super(itemView);
factImage = itemView.findViewById(R.id.factImage);
title = itemView.findViewById(R.id.title);
more = itemView.findViewById(R.id.more);
}
}
}
How can I pass data to dialog fragment?
test it
adapter:
Bundle args = new Bundle();
args.putString("key", "value");
BottomSheet bottomSheet = new BottomSheet();
bottomSheet .setArguments(args);
bottomSheet .show(((FragmentActivity) context).getSupportFragmentManager(),bottomSheet.getTag());
bottom sheet fragment :
Bundle mArgs = getArguments();
String myValue = mArgs.getString("key");
If I get you right, you can try to make one interface:
public interface DataTransferInterface {
public void onSetValues(ArrayList<?> al);
}
Then impletent this inteface in your Fragment/Activity/BottomSheetDialogFragment and pass it as listener to your adapter's constructor:
#Override
public void onSetValues(List<Fact> list) {
if (list.size() < 1) {
txtEmptyAdapter.setVisibility(View.VISIBLE);
}
}
public FactsAdapter(List<Facts> factList, Context context, DataTransferInterface listener) {
this.factList = factList;
this.context = context;
this.listener = listener;
}
Now it's easy to call this listener wherever you need and get required data in your Fragment/Activity/BottomSheetDialogFragment, like that:
listener.onSetValues(factList);
Everything works well and my onClick in my recyclerView is working in getting the positions of my items, but what my design calls for is to be able to click an item of the recyclerView and open up a new activity (as a popover or pop up). I can achieve this but my problems comes with the information I need to display on the popover. The information comes like this inside the activity (inside a Firebase value call)
attributeList.removeAll(attributeList);
for (DataSnapshot child : dataSnapshot.child("Attribute").getChildren()){
Attribute attribute = child.getValue(Attribute.class);
attribute_list newAttributeList = new attribute_list( attribute.Name + ": " + attribute.Value);
attributeList.add(newAttributeList);
}
attributeAdapter = new attribute_list_adapter(attributeList, getContext());
recyclerAttribute.setAdapter(attributeAdapter);
This works perfectly for displaying the information, but there's more then just a "value" and a "name" associated with the click.
Basically when I select an item, I need to get the position of the item clicked (which I have) and compare it to the position inside attributeList so I can call a Firebase call (or pass the data somehow) to the popover to display values from the "Attribute" class (such as Name, Value, Description, and another list (recyclerView).
My recyclerView:
public class attribute_list_adapter extends RecyclerView.Adapter<attribute_list_adapter.ViewHolder> {
private List<attribute_list> listItems;
private Context context;
public attribute_list_adapter(List<attribute_list> listItems, Context context) {
this.listItems = listItems;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.attribute_list, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
attribute_list listItem = listItems.get(position);
holder.txtTitle.setText(listItem.getTxtTitle());
}
#Override
public int getItemCount() {
return listItems.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView txtTitle;
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
txtTitle = (TextView) itemView.findViewById(R.id.txtTitle);
}
#Override
public void onClick(View v) {
}
}
}
This is example:
public class attribute_list_adapter extends RecyclerView.Adapter<attribute_list_adapter.ViewHolder> {
private List<attribute_list> listItems;
private Context context;
public attribute_list_adapter(List<attribute_list> listItems, Context context) {
this.listItems = listItems;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.attribute_list, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.itemView.setOnClickListener(new View.onClickListener() {
#Override
public void onClick(View v) {
onItemClickListener.onItemClick(position);
}
});
}
#Override
public int getItemCount() {
return listItems.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView txtberita;
ImageView imgberita;
TextView txtnama;
public ViewHolder(View itemView) {
super(itemView);
txtnama = (TextView) itemView.findViewById(R.id.txtnama);
txtberita = (TextView) itemView.findViewById(R.id.txtberita);
imgberita = (ImageView) itemView.findViewById(R.id.imgberita);
}
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener){
this.onItemClickListener = onItemClickListener;
}
OnItemClickListener onItemClickListener;
public interface OnItemClickListener{
void onItemClick(int position);
}
}
your Activity. in Oncreate()
public class TestActivity extends AppCompatActivity implements attribute_list_adapter.OnItemClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
attribute_list_adapter adapter = new attribute_list_adapter(listItems, this);
adapter.setOnItemClickListener(this);
}
#Override
public void onItemClick(int position) {
// code here
}
}
Create an interface something like
public interface OnSingleItemClickListener{
void onSingleItemClick(int position);
}
Then implement it on your ViewHolder like this
public class ViewHolder extends RecyclerView.ViewHolder implements OnSingleItemClickListener {
public ViewHolder(View itemView) {
super(itemView);
}
#Override
void onSingleItemClick(int position){
if(listItems.get(position) == listItems.get(getAdapterPosition)){
// TODO do something here
}
}
now on your OnBindViewHolder inside your adapter you must do this.
holder.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
holder.onSingleItemClick(position);
}
}):
In my MainActivity I have something like this:
recyclerAdapter = new RecyclerAdapter(this, arrayList);
recyclerView.setAdapter(recyclerAdapter);
To update my RecyclerView, I do: (in MainActivity, too)
Item item = new Item();
item.setId(id);
item.setMessage(message);
arrayList.set(position, item);
recyclerAdapter.notifyItemChanged(position);
I want to have a button within every RecyclerView list item which can enable/disable the current entry. Therefore I need to get the current toggle state.
My problem is, how can I update the RecyclerView in MainActivity from within my ViewHolder?
RecyclerView.ViewHolder:
public class SetViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{//, View.OnLongClickListener{
public ImageView toggle;
public SetViewHolder(View itemView){
super(itemView);
toggle = (ImageView) itemView.findViewById(R.id.img_main_card_toggle);
toggle.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (v.getId() == toggle.getId()) {
int clicked_position = getAdapterPosition();
//TODO update Item of RecyclerView of MainActivity
}
}
My Recycler.Adapter:
public class RulesAdapter extends RecyclerView.Adapter<SetViewHolder>{
private Activity activity;
List<Item> items = Collections.emptyList();
private OnTapListener onTapListener;
public RulesAdapter(Activity activity, List<Item> items){
this.activity = activity;
this.items = items;
}
#Override
public SetViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rules_list_item,parent,false);
return new SetViewHolder(view);
}
#Override
public void onBindViewHolder(SetViewHolder holder, final int position) {
holder.recevied_message.setText(items.get(position).getReceived_message());
holder.reply_message.setText(items.get(position).getReply_message());
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(onTapListener != null){
onTapListener.OnTapView(position);
}
}
});
}
#Override
public int getItemCount() {
return items.size();
}
public void setOnTapListener(OnTapListener onTapListener){
this.onTapListener = onTapListener;
}
}
Define an Interface.
public interface OnRecyclerItemToggleClickListener {
void onToggleClick(int adapterPosition);
}
Implement this in your adapter. And pass the adapter instance to the ViewHolder through a setter method in the onCreateViewHolder callback.
public class SetViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{//, View.OnLongClickListener{
public ImageView toggle;
private OnRecyclerItemToggleClickListener listener;
public SetViewHolder(View itemView){
super(itemView);
toggle = (ImageView)
itemView.findViewById(R.id.img_main_card_toggle);
toggle.setOnClickListener(this);
}
public void setRecyclerItemToggleClickListener( OnRecyclerItemToggleClickListener listener) {
this.listener = listener;
}
#Override
public void onClick(View v) {
if (v.getId() == toggle.getId()) {
int clicked_position = getAdapterPosition();
//TODO update Item of RecyclerView of MainActivity
listener.onToggleClick(clicked_position);
}
}
In your adapter:
#Override
public SetViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rules_list_item,parent,false);
SetViewHolder holder = new SetViewHolder(view);
holder.setOnRecyclerItemToggleClickListener(this);
return holder;
}
#Override public void onToggleClick(int adapterPosition) {
// you will get the callback here when the toggle button is clicked.
// you can update the ArrayList here.
// Or similarly, call an interface method to Activity.
}
And call this onToggleClick method from ViewHolder when the toggle is clicked. You will get a callback to adapter, where you can update the ArrayList. Otherwise you can have another similar Interface to give callback to Activity from the adapter.
You just have to add a static function and make items static too:
public static ArrayList<Items> getAreayList()
{
return items;
}
And get this function in MainActivity:
onStart()
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.
I have a recyclerview to show facebook like newsfeed with a comment button. I cant figure out how to show a dialog when user clicks on comment button. All the solutions I found here were to handle the entire item's click but not its internal view. I tried this soultion also. How to handle multiple layout clicks in recyclerView in Android
Here is my adapter class.
public class NewsfeedAdapter extends RecyclerView.Adapter<NewsfeedAdapter.NewsfeedViewHolder> {
private final LayoutInflater inflater;
private Context context;
ArrayList<NewsfeedItem> data= new ArrayList<NewsfeedItem>();
public NewsfeedAdapter(Context context,ArrayList<NewsfeedItem> data){
inflater= LayoutInflater.from(context);
this.data=data;
this.context = context;
}
#Override
public NewsfeedViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.custom_newsfeed_row, parent, false);
NewsfeedViewHolder holder = new NewsfeedViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(NewsfeedViewHolder newsfeedViewHolder, int i) {
NewsfeedItem current = data.get(i);
newsfeedViewHolder.username.setText(current.username);
newsfeedViewHolder.icon.setImageResource(current.iconid);
newsfeedViewHolder.timestamp.setText((CharSequence) current.timestamp);
newsfeedViewHolder.news.setText(current.news);
}
#Override
public int getItemCount()
{
return data.size();
}
class NewsfeedViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView news, username, timestamp, comment_btn, like_btn;
ImageView icon;
private NewsfeedClickInterface clickListener;
public NewsfeedViewHolder(View itemView) {
super(itemView);
news = (TextView) itemView.findViewById(R.id.news);
timestamp = (TextView) itemView.findViewById(R.id.timestamp);
username = (TextView) itemView.findViewById(R.id.username);
icon = (ImageView) itemView.findViewById(R.id.profile_img);
comment_btn = (TextView) itemView.findViewById(R.id.comment_btn);
comment_btn.setTag("comment");
comment_btn.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (clickListener != null) {
clickListener.onItemClicked(getPosition(), v.getTag().toString());
}
}
}
public interface NewsfeedClickInterface {
public void onItemClicked(int position, String tag);
}
}
First define an interface in your viewholder. And when button is clicked, call this interface.
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public interface ViewHolderClickListener {
public void onItemClick(View caller, int position);
}
public ViewHolderClickListener mListener;
public ViewHolder(View itemView, ViewHolderClickListener listener) {
super(itemView);
mListener = listener;
//other initializations...
}
#Override
public void onClick(View v) {
mListener.onItemClick(v, getPosition());
}
}
Then create another interface in a separate file, let's say you create this interface in a class called Commons:
public class Commons {
public interface OnRecyclerItemClickedListener{
public void onRecyclerItemClicked(String parameter);
}
}
Then let your fragment/activity implement that interface. And pass this interface to your adapter's constructor as a parameter.
public class MyFragment extends Fragment implements Commons.OnRecyclerItemClickedListener{
#Override
public void onRecyclerItemClicked(String productId) {
//do whatever you want on click
}
}
Pass this interface to your adapter's constructor:
//here "this" parameter is your listener since your fragment implements
//the interface you defined
MyRecyclerViewAdapter adapter = new MyRecyclerViewAdapter(items, R.layout.yourlayout, getContext(), this);
and in your adapter, create an instance of the interface you defined in Commons class and set it in your constructor. Then create your viewholder in onCreateViewHolder method. Finally, call the interface you defined in your Commons class in your Viewholder's click interface:
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder>{
private OnRecyclerItemClickedListener onRecyclerItemClickedListener;
public MyRecyclerViewAdapter(List<Item> items, int rowLayout, Context context, OnRecyclerItemClickedListener onRecyclerItemClickedListener){
this.items = items;
this.rowLayout = rowLayout;
this.mContext = context;
this.onRecyclerItemClickedListener = onRecyclerItemClickedListener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(rowLayout, parent, false);
ViewHolder holder = new ViewHolder(v, new ViewHolder.ViewHolderClickListener() {
#Override
public void onItemClick(View caller, int position) {
onRecyclerItemClickedListener.onRecyclerItemClicked(put_parameters_if_you_want);
}});
return holder;
}
}
It is a little complicated, but here is the explanation of what you do: When button is clicked, your button click listener calls another listener(which was defined in your viewholder), and that listener calls another listener which was implemented in your fragment.
That is all you need to do.
Inside
#Override
public void onClick(View v) {
if(view.getId() == comment_btn.getId()){
Log.d("LOGTAG","Bingo !!! Your view Clicked.");
}
if (clickListener != null) {
clickListener.onItemClicked(getPosition(), v.getTag().toString());
}
}
you can check the Id's of the views and fire different click listeners according to which view was clicked.
like
comment_btn.setOnClickListener(this);
anotherButton.setOnClickListener(this);
switch (v.getId())
case R.id.comment_btn:
code goes here
case R.id.another_button:
hope this helps.