Option menu in recycler view adapter - android

I would like to like to ask you how I call a method in activity from adapter recycler view.
In function buildRecyclerView there is set up the adapter:
private void buildRecyclerView() {
offerAdapter = new OfferAdapter();
recyclerView.setAdapter(offerAdapter);
}
In class OfferAdapter.java there is created submenu for each item and with onMenuItemClickListener:
#Override
public void onBindViewHolder(NoteHolder holder, int position) {
PopupMenu popup = new PopupMenu(mCtx, holder.button);
popup.inflate(R.menu.menu);
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
// TODO here I want to call delete item in MyOfferFragment.java
}
The main question: How I can call from *onMenuItemClickListnere* the function in *MyOfferFragment*.
Thank you very much in advance

You can pass a listener object in the constructor which implements by fragment OR activity
/**
* item click interface of adapter
*/
public interface OfferAdapterListener {
void onItemClick(int position)
}
This interface implent by fragment
/**
* On item clicked Implement Method from adapter listener.
*
* #param position
*/
#Override
public void onItemClick(int position) {
// Here you can call that method
}
then you pass this listener in the constructor of the adapter.
private void buildRecyclerView() {
offerAdapter = new OfferAdapter(this);
recyclerView.setAdapter(offerAdapter);
}
In the constructor, you can assign like this
private OfferAdapterListener mOfferAdapterListener;
public OfferAdapter(OfferAdapterListener mOfferAdapterListener) {
this.mOfferAdapterListener = mOfferAdapterListener
}
}
Now you can use this listener by setting click listener on anyViwe like this
holder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mOfferAdapterListener.onItemClick(position);
}
});
It returns to call the method of onItemClick which implements this method.
OR
You can pass activity or fragment context in the constructor like above and call it through by it reference like this
((MainActivity) mActivity).methodName(arguments);
Here is mActivity reference context which you pass through in constructor.

You can add the MyOfferFragment to your adapter constructor.
private void buildRecyclerView() {
offerAdapter = new OfferAdapter(this); // Adding fragment to constructor
recyclerView.setAdapter(offerAdapter);
}
In OfferAdapter.java:
private MyOfferFragment mFragment; // field variable
OfferAdapter (MyOfferFragment fragment){
mFragment = fragment;
}
You can then access MyOfferFragment methods via mFragment:
mFragment.deleteItem();
However, I think it is a more conventional way to just move methods related to RecyclerView into the adapter if possible. You can refer to this if you want to delete an item from RecyclerView: Android RecyclerView addition & removal of items

Related

Card View Click on card to move to next activity

I am working on a project in android and i just learn about card view class.
I made a card who generates a toast when user clicks on it.
But i also want my card to call another activity when user clicks on it.
I am posting part of my code below.
btnProceed.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showToast("Proceed to the next step");
Intent intent = new Intent(MyLocationUsingLocationAPI.this, click_picture.class);
startActivity(intent);
}
});
I have made changes in my code as you said but when i click on proceed button my app crashes.What is wrong with code?
the main idea here is to define your actionClickListener
1. create a custom recycleView Adapter
public class AdapterCustomList extends RecyclerView.Adapter<RecyclerView.ViewHolder>
2. define onItemClickListener interface
public interface OnItemClickListener {
void onItemClick( whateverArgsYouWant );
}
3. make an attribute of the interface and define a setter for it
private OnItemClickListener mOnItemClickListener;
public void setOnItemClickListener(final OnItemClickListener mItemClickListener) {
this.mOnItemClickListener = mItemClickListener;
}
4. append a listener to each item while its created in the adapter class
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
...
OriginalViewHolder vItem = (OriginalViewHolder) holder;
vItem.baseCard.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mOnItemClickListener != null) {
mOnItemClickListener.onItemClick( whateverArgsYouWant );
}
}
});
}
this method will be called when items of recycle view is created (in case you use card view inside a recycle view)
5. use your onClickListener in the Activity you want
AdapterCustomList mAdapter = new AdapterCustomList (getActivity(), recyclerView,yourListItemsHere));
recyclerView.setAdapter(mAdapter);
// on item list clicked
mAdapter.setOnItemClickListener(new AdapterPostList.OnItemClickListener() {
#Override
public void onItemClick( whateverArgsYouWant ) {
...
statements
...
}
});

Update RecyclerView from Dialog

how to update recyclerview from a dialog which is in another class?
My dialog is as a separate class which is called from mainActivity. When I do changes in database, I would like to update recyclerview, which is on mainActivity.
Dialog:
public class Dialog {
DatabaseExecutor databaseExecutor = new DatabaseExecutor();
private final Activity activity;
private final List<Passenger> passengers;
private final int position;
public Dialog (final Activity activity, final List<Passenger> passengers, final int position){
this.activity = activity;
this.passengers = passengers;
this.position = position;
}
public void showDialog (){
final BottomSheetDialog dialog = new BottomSheetDialog(activity);
dialog.setContentView(R.layout.custom_dialog);
final AppCompatImageView dial, message, info, paid, edit, delete;
final AppCompatTextView name;
name = dialog.findViewById(R.id.dialog_name);
paid = dialog.findViewById(R.id.dialog_paid);
name.setText(passengers.get(position).getName());
if(passengers.get(position).isPaid())
paid.setImageResource(R.drawable.money_paid_72);
else
paid.setImageResource(R.drawable.money_unpaid_72);
paid.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Passenger passenger = passengers.get(position);
if (!passengers.get(position).isPaid()){
passenger.setPaid(true);
passenger.setTumblr(R.drawable.money_paid);
passenger.setUser(R.drawable.user_icon);
paid.setImageResource(R.drawable.money_paid_72);
}
else {
passenger.setPaid(false);
passenger.setTumblr(R.drawable.money_unpaid);
passenger.setUser(R.drawable.user_icon_unpaid);
paid.setImageResource(R.drawable.money_unpaid_72);
}
databaseExecutor.updatePassenger(activity, passenger);
}
});
dialog.show();
}
}
P.s. when this dialog was in mainActivity, I just called populateData method and it worked. But how to refresh it from this Dialog class?
You can use callback with dialog in MainActivity,
public interface DialogCallback {
public void onDialogCallback();
}
Your Dialog constructor should be,
DialogCallback callback;
public Dialog (final Activity activity, final List<Passenger> passengers, final int position, DialogCallback callback){
this.activity = activity;
this.passengers = passengers;
this.position = position;
this.callback = callback;
}
In your Dialog button click use below code,
paid.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Passenger passenger = passengers.get(position);
if (!passengers.get(position).isPaid()){
passenger.setPaid(true);
passenger.setTumblr(R.drawable.money_paid);
passenger.setUser(R.drawable.user_icon);
paid.setImageResource(R.drawable.money_paid_72);
}
else {
passenger.setPaid(false);
passenger.setTumblr(R.drawable.money_unpaid);
passenger.setUser(R.drawable.user_icon_unpaid);
paid.setImageResource(R.drawable.money_unpaid_72);
}
databaseExecutor.updatePassenger(activity, passenger);
callback.onDialogCallback(); // Add this line
}
});
In your MainActivity use below code,
Dialog dialog = new Dialog(this, passengers, position, new DialogCallback() {
#Override
public void onDialogCallback() {
// Update recycler view code here
}
});
dialog.showDialog();
In Dialog :
Have an interface
public interface onDialogFinishCallback
{
void refreshRecyclerView();
}
Now implement the above in your activity.
before dismiss the dialog or after the db change operation call
callback.refreshRecyclerView
A direct solution would be to call method on activity you passed to the dialog. There refresh data of recyclerview and notifyDataSetChanged() or appropriate.
A more general and imo better, architecture-related solution is to use Room or similar db, where you can observe data for changes. Let's say data in the db is changed anywhere. All the places where this data is observed (like with LiveData), data is refreshed. If you also use Paging library, data is refreshed and animated in recyclerview too.
Dialog shouldn't refresh RecyclverView directly. Instead you should pass listener from activity. Activity can refresh recycler if needed with notifyDataSetChanged.
Usually dialog should be 'dumb' ui and you shouldn't give it too much control, especially not over elements that are not shown inside dialog. Such approach will make your dialogs more reusable and easy to maintain.
Write an interface in your dialog
public interface onClickInterface{
public void updateRecyclerView(int position);
}
declare new variable for this interface in your dialog class
private onClickInterface mOnClickInterface;
then call method updateRecyclerView() from dialog class where you want to update recyclerview
mOnClickInterface.updateRecyclerView(position);
then implement your MainActivity for this interface and override this method
#override
public void updateRecyclerView(int position){
//alter your list which you are passing to your adapter
Passenger passenger = passengers.get(position);
passenger.setPaid(true);
rAdapter.notifyDatasetChanged();
}

Issue in Button Text change from Dialog Fragment

Here there is minor issue Like I had Recyclerview in dialog fragment.ie name of bank in recyclerview When we select one bank in recyclerview and after dialogfragment dismiss that name should be appear on Button ie when we selected Union Bank from dialog fragment it should appear on button.Issue is when we click on button then its text changes rather then on time of dismiss listener
here is Dialog dismissal code:
mRecyclerView.addOnItemTouchListener(new RecyclerTouchListener(getContext(), mRecyclerView, new ClickListener() {
#Override
public void onClick(View view, final int position) {
Employee e = bank.get(position);
Toast.makeText(getContext(), e.getBank_id() + "" + e.getBank_name(), Toast.LENGTH_SHORT).show();
getDialog().setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialogInterface) {
Employee e = bank.get(position);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor edit = sp.edit();
edit.putString("bankname", e.getBank_name());
edit.commit();
}
});
c.onItemSelect(e.getBank_name());
onDismiss(getDialog());
}
Here is onclick event where dialog opens and where the value should be printed:
select_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentManager fm=getFragmentManager();
DialogRecyclerview dr = new DialogRecyclerview(AccountManagement_banks.this,callback);
dr.setRetainInstance(true);
dr.show(getSupportFragmentManager(), "Dialog");
SharedPreferences st = PreferenceManager.getDefaultSharedPreferences(AccountManagement_banks.this);
String mode=st.getString("bankname","");
select_button.setText(mode);
Toast.makeText(getApplication(),mode,Toast.LENGTH_SHORT).show();
}
});
Same in:
#Override
public void onItemSelect(String text) {
select_button.setText(text);
}
Here I had created new Interface:
public interface CallBack {
void onItemSelect(String text);}
just create a callback and implement it on your main class (where you want to display the name) and pass the callback instance to adapter. Now dialog fragment, now when you are selecting any item just call callback function which is overridden in main calss and inside this function just change the text of your button.
public interface CallBack {
void onItemSelect(String text);
}
implement this in your main class like
public class MainActivity extends Activity implements CallBack {
.
.
.
public void onItemSelect(String text){
button.setText(text);
}
.
.
}
when you are opening your dialogfragment from your main activity just pass MainActivity.this as an argument in the dialog constructor. And in your Dialog class constructor write your code like this
private Callback callback;
public YourDialog(Context context, Callback callback){
this.callback = callback;
}
and when you selecting list item just call
callback.onItemSelect(e.getBank_name());
Hope it will help you out.

How to receive callback from Activity class into ListView Adapter class in android?

I have Activity with a custom Listview and button. Now
I want to implement Activity button callback in adapter class.
How its possible in Android ?
Please give me suggestion.
FIRST SOLUTION OWN LISTENER
It should be done by Listeners, create Listener interface in Activity, next implement interface in Adapter class. Set Adapter object as listener of Activity and last thing run Listener methods when You want to do something in Adapter.
class Activity{
private Listener listener;
//your activity listener interface
public interface Listener{
onButtonClick();
}
private void setListener(Listener listener){
this.listener=listener;
}
//example method
private void youMethod(){
YourAdapter adapter=new YourAdapter();//YourAdapter class implements Listener
//here You say that adapter is You listener
setListener(adapter);
//bind button
Button button = (Button)findViewById(R.id.buttonName);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v)
{
//run listener after button click
buttonIsClicked();
//or
//listener.onButtonClick();
}
});
}
private void buttonIsClicked(){
//here use method
listener.onButtonClick();
}
}
//EXAMPLE ADAPTER
class YourAdapter implements Activity.Listener{
//...adapter code
void onButtonClick(){
//your code on button click
}
}
SECOND SOLUTION ADAPTER AS ONCLICKLISTENER
class Activity{
//example method
private void youMethod(){
YourAdapter adapter=new YourAdapter();
//bind button
Button button = (Button)findViewById(R.id.buttonName);
//set adapter as onClickListener
button.setOnClickListener(adapter);
}
}
//EXAMPLE ADAPTER
class YourAdapter implements OnClickLstener{
//...adapter code
public void onClick(View v)
{
//adpater code after click
}
}
THIRD SOLUTION - IT CAN BE DONE WITHOUT INTERFACE ( NOT GOOD PRACTICE )
Just add method to Your adapter and use it:
button.setOnClickListener(new OnClickListener() {
public void onClick(View v)
{
//use adapter
adapter.onButtonClick();
}
});
//EXAMPLE ADAPTER WITHOUT INTERFACE
class YourAdapter{
//...adapter code
void onButtonClick(){
//your code on button click
}
}

Fragment communication - Fragment to fragment

I need help on understanding how the following scenario works and how to achieve the result.
I have a class called ShoppingCart.
It has a method called addItemsToShoppingCartFromPreviousOrder.
Now I have a fragment called PreviousOrderFragment with onCreateView method which is using the RecyclerView. Its a list of previous orders.
I have multiple lists. Now I want to know how to call the addItemsToShoppingCartFromPreviousOrder method from ShoppingCart into my fragment.
so that when the user clicks a list, it will add to the cart.
You need do that:
In you Adapter of RecycleView put:
private ItemListener mListener;
...
public void setmListener(ItemListener mListener) {
this.mListener = mListener;
}
...
public interface ItemListener {
void onItemSelected(Item item);
}
Item = The item selected
them...
In your ViewHolder of Adapter put that:
public class Holder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView tv_id;
public TextView tv_url;
public TextView tv_login;
public Holder (View itemView) {
super(itemView);
tv_id = (TextView) itemView.findViewById(R.id.tv_id);
tv_url = (TextView) itemView.findViewById(R.id.tv_url);
tv_login = (TextView) itemView.findViewById(R.id.tv_login);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (mListener != null) {
Integer position = Integer.valueOf(getLayoutPosition());
mListener.onUserSelected(mList.get(position));
}
}
}
OBS: That ViewHolder is a InnerClass of Adapter
Them all you need do is:
In your fragment
mRecycleViewAdapter.setmListener(this)
Them make your fragment:
public class MyFragment extends Fragment implements MyRecycleViewAdapter.ItemListener
And override :
#Override
public void onItemSelected(Item item) {
//call addItemsToShoppingCartFromPreviousOrder
}
Here is a example,
see SearchFragment.java and UsersListAdapter.java
1- Create a interface call it for ex. OnItemClicked
Interface OnItemClick{
void onItemClicked(/*pass your selected object*/);
}
2- make the fragment implement this interface
Class PreviousOrderFragment extends Fragment implements OnItemClicked{
void onItemClicked(/*pass your selected object*/){
/** here you have the select object when item clicked from the activity **/
addItemsToShoppingCartFromPreviousOrder();
}
}
3- Take an instance from the fragment in the Activity
Class YOUR_Activity extends Activity {
PreviousOrderFragment fragment = new PreviousOrderFragment ();
/// in the onClick event
public onClick(View v){
fragment.onItemClicked(/**pass the selected object*/);
}
}
see this answer, Already explained all the possible ways to make communication between fragments.
But a good way is to use EventBus when you have complicated communication between Many Activities and Fragments, It's much easy and fast,and a better approach then any of this described in above linked answer.

Categories

Resources