I have an activity that creates a tab layout inside of it. The layout contains two fragments. The first fragment has a recycler view. Each card in the recycler view has a check box and a string.
If I click on the checkbox I want to send this card's string to a List located in the activity so I can populate it onto the second tab fragment.
On the first fragment cards I have an on click that sets boolean to true which is saved on an object. I am trying to figure out how to grab this object when it is clicked and send it to the activities list.
Activity-
public class MainActivity extends AppCompatActivity {
public static List toSendList = new ArrayList();
...more code
}
Recycler Adapter-
//initialize variables...
CheckBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (CheckBox.isChecked()) {
//MainActivity.toSendList.add(Obj);
obj.setIsChecked(true);
}
}
});
... more code
You might try EventBus and see if you like it. With it, you define an
'event' which can also be the object that you want to pass to your activity (or an event which wraps it). In the receiving activities, add your Subcribers. You then pass events/objects by calling
EventBus.getDefault().post(new CustomEvent());
and any place where a Subcriber is still attached will receive the event.
You can implement a listener which you will use on the Activity. For example:
You create a interface for a click listener.
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.PhotoHolder> {
// ... all the code
public interface RecyclerViewOnClickListener(/* same arguments as above */);
}
On your view holder.
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public ViewHolder(View v) {
super(v);
// ... do all the initialization
v.setOnClickListener(this);
}
#Override
public void onClick(View v) {
mOnClickListener(int position /* or whatever argument you like */)
}
}
On your RecyclerAdapter you store a listener for the click. So the adapter would end up with more code:
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.PhotoHolder> {
// ... all the code
public interface RecyclerViewOnClickListener(/* same arguments as above */);
public RecyclerAdapter(RecyclerViewOnClickListener onClickListener) {
mOnClickListener = onClickListener;
}
}
So finally, in your Activity you just instantiate the RecyclerViewOnClickListener and pass it as an argument for the adapter.
try this :
Activity-
public class MainActivity extends AppCompatActivity {
public static List toSendList = new ArrayList();
...more code
public setPassData(String string)
{
//do something with this string
}
}
Fragment A/B
public void setPassData(String string)
{
((ActivityName)getActivity()).setPassData(string);
}
Recycler Adapter-
//initialize variables...
CheckBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (CheckBox.isChecked()) {
//MainActivity.toSendList.add(Obj);
obj.setIsChecked(true);
((FragmentName)mContext).setPassData(SomeStringToPass);
}
}
});
Related
I am trying to implement a "Pin Message" functionality on the chat app I'm developing.
Chat Activity looks like this:
I have a TextView above the chat RecyclerView and would like to set the text of that to the TextView value inside the RecyclerView. I can get the string value of what's inside the RecyclerView by using a PopupMenu (inside its adapter class) by showing it in a Toast for now.
How should I implement this? Thank you!
P.S. I'm still using Java.
I finally found a solution for this one. Link to SO post here -> LINK
First create an interface called PinMessageListener
public interface PinMessageListener {
void onPin(String value);
}
second, implement this interface in your activity or fragment
public class YourActivityOrFragment extends AppCompatActivity implement PinMessageListener {
...
...
...
#Override
public void onPin(String value) {
yourTextView.setText(value);
}
...
}
third, pass this interface in your recycler adapter
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
//this refers to PinMessageManager
YourRecyclerViewAdapter adapter = new YourRecyclerViewAdapter(this);
...
}
your recycler adapter must look like this:
public YourRecyclerViewAdapter extends RecyclerView.Adapter<YourViewHolder> {
private final PinMessageListener pinMessageListener;
public YourRecyclerViewAdapter(PinMessageListener pinMessageListener) {
this.pinMessageListener = pinMessageListener;
}
onCreateViewHolder(...) {
return new YourViewHolder(pinMessageListener);
}
and your viewHolderClass must be look like this:
public YourViewHolder extends RecyclerView.ViewHolder {
private final PinMessageListener pinMessageListener;
public YourViewHolder(View rootView) {
super(rootView);
this.pinMessageListener = pinMessageListener;
}
public void bind(ModelClass model) {
yourTextView.onClickListener((view) -> pinMessageListener.onPin(yourTextView.getText().toString());
}
And that's it.
I am trying to show data in toolbar. I have recyclerview where I set movies name. when I click any movie name, the name show in toolbar. I defined the onclick method in adapter class.
This is adapter class
Make public method in adapter class and call that method in onClick
ExampleAdapter.java
holder.tvMovie.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onSelectMovie(list.get(holder.getAdapterPosition()).getname());
}
}
});
public void onSelectMovie(String movieName)
{
}
Override onSelectMovie method where you call the adapter constructor
exampleAdapter = new ExampleAdapter() {
#Override
public void onSelectMovie(String movieName) {
super.onSelectImage(movieName);
setTitle(movieName);
}
};
I'm trying to detect from my mainActivity wheter the user does a normal click or a long press because depend of it I need to do one thing or another, and I have the object of my SQLite on my MainActivity and not in my Adapter, I do not know if it's better to detect it on the Adapter or in MainActivity.
My adapter is a normal one which has a ViewHolder and items on it, but I need to detect the click on the view not on an specific view on row, can you guide me how to?
I'd like to get like a callback that detects when user does one action and depends of it do one thing or another
EXPLANATION
On my main activity I have the private DatabaseHelper db; object so I'd like to do something like if he does onClick view the detail onLongClick show a dialog to delete it.
Hope you understand my issue.
You might want to use an interface for that purpose, like such:
Add this to your Custom Adapter:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private ItemClickListener mClickListener;
public void setClickListener(ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
public interface ItemClickListener {
void onItemClick(int position);
boolean onItemLongClick(int position);
}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
itemView.setHapticFeedbackEnabled(true); // vibration feedback on long click
}
#Override
public void onClick(View view) {
if (mClickListener != null) mClickListener.onItemClick(getAdapterPosition());
}
#Override
public boolean onLongClick(View view) {
if (mClickListener != null) mClickListener.onItemLongClick(getAdapterPosition());
return true;
}
}
}
And in your MainActivity implement the ItemClickListener and overwrite its methods:
public class MainActivity extends AppCompatActivity
implements MyAdapter.ItemClickListener {
#Override
public void onItemClick(int position) {
//TODO Add OnClick behaviour
}
#Override
public boolean onItemLongClick(int position) {
return false;
//TODO Add OnLongClick behaviour
}
}
You have to use Adapter for this purpose, additionally you have to use GestureDetector for long press, AlertDialog for confirmation message and handle requisite sqllite accordingly.
Follow the Android guide about input Events here.
TLDR; You should use OnClickListener and OnLongClickListener
I have a Button on Listview and a custom adapter that loads the ListView. I want to call the Button onClickListner in main class not in the adapter class. how can i do this.
You can create one Global Interface
Like this
package com.radiofrance.interfaces;
public abstract class GlobalInterface implements eventInterface {
public void onClick(int values) {
}
public void onCancel() {
}
}
Then Implement this interface in Your Activity from which you call your adapter
public class SampleClickListener extends GlobalInterface {
#Override
public void onClick(final int values, final boolean state) {
}
}
now in your adapter pass this object of interface
Adapter adt = new Adpater(this, R.layout.row, arrRow,
new SampleClickListener());
and from your adapter call
listner.onClick(position, false);
Thanks
Is it possible to call method that is defined in Activity from ListAdapter?
(I want to make a Button in list's row and when this button is clicked, it should perform the method, that is defined in corresponding Activity. I tried to set onClickListener in my ListAdapter but I don't know how to call this method, what's its path...)
when I used Activity.this.method() I get the following error:
No enclosing instance of the type Activity is accessible in scope
Any Idea ?
Yes you can.
In the adapter Add a new Field :
private Context mContext;
In the adapter Constructor add the following code :
public AdapterName(......, Context context) {
//your code.
this.mContext = context;
}
In the getView(...) of Adapter:
Button btn = (Button) convertView.findViewById(yourButtonId);
btn.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
if (mContext instanceof YourActivityName) {
((YourActivityName)mContext).yourDesiredMethod();
}
}
});
replace with your own class names where you see your code, your activity etc.
If you need to use this same adapter for more than one activity then :
Create an Interface
public interface IMethodCaller {
void yourDesiredMethod();
}
Implement this interface in activities you require to have this method calling functionality.
Then in Adapter getView(), call like:
Button btn = (Button) convertView.findViewById(yourButtonId);
btn.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
if (mContext instanceof IMethodCaller) {
((IMethodCaller) mContext).yourDesiredMethod();
}
}
});
You are done. If you need to use this adapter for activities which does not require this calling mechanism, the code will not execute (If check fails).
You can do it this way:
Declare interface:
public interface MyInterface{
public void foo();
}
Let your Activity imlement it:
public class MyActivity extends Activity implements MyInterface{
public void foo(){
//do stuff
}
public onCreate(){
//your code
MyAdapter adapter = new MyAdapter(this); //this will work as your
//MyInterface listener
}
}
Then pass your activity to ListAdater:
public MyAdapter extends BaseAdater{
private MyInterface listener;
public MyAdapter(MyInterface listener){
this.listener = listener;
}
}
And somewhere in adapter, when you need to call that Activity method:
listener.foo();
Original:
I understand the current answer but needed a more clear example. Here is an example of what I used with an Adapter(RecyclerView.Adapter) and an Activity.
In your Activity:
This will implement the interface that we have in our Adapter. In this example, it will be called when the user clicks on an item in the RecyclerView.
public class MyActivity extends Activity implements AdapterCallback {
private MyAdapter myAdapter;
#Override
public void onMethodCallback() {
// do something
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myAdapter = new MyAdapter(this);
}
}
In your Adapter:
In the Activity, we initiated our Adapter and passed this as an argument to the constructer. This will initiate our interface for our callback method. You can see that we use our callback method for user clicks.
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private AdapterCallback adapterCallback;
public MyAdapter(Context context) {
try {
adapterCallback = ((AdapterCallback) context);
} catch (ClassCastException e) {
throw new ClassCastException("Activity must implement AdapterCallback.", e);
}
}
#Override
public void onBindViewHolder(MyAdapter.ViewHolder viewHolder, int position) {
// simple example, call interface here
// not complete
viewHolder.itemView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
try {
adapterCallback.onMethodCallback();
} catch (ClassCastException e) {
// do something
}
}
});
}
public static interface AdapterCallback {
void onMethodCallback();
}
}
Basic and simple.
In your adapter simply use this.
((YourParentClass) context).functionToRun();
For Kotlin:
In your adapter, simply call
(context as Your_Activity_Name).yourMethod()
One more way is::
Write a method in your adapter lets say
public void callBack(){}.
Now while creating an object for adapter in activity override this method.
Override method will be called when you call the method in adapter.
Myadapter adapter = new Myadapter() {
#Override
public void callBack() {
// dosomething
}
};
In Kotlin there is now a cleaner way by using lambda functions, no need for interfaces:
class MyAdapter(val adapterOnClick: (Any) -> Unit) {
fun setItem(item: Any) {
myButton.setOnClickListener { adapterOnClick(item) }
}
}
class MyActivity {
override fun onCreate(savedInstanceState: Bundle?) {
var myAdapter = MyAdapter { item -> doOnClick(item) }
}
fun doOnClick(item: Any) {
}
}
For kotlin you could do something like :
if(context is MainActivity){ context.functionToCall(values) }
if (parent.getContext() instanceof yourActivity) {
//execute code
}
this condition will enable you to execute something if the Activity which has the GroupView that requesting views from the getView() method of your adapter is yourActivity
NOTE : parent is that GroupView