I have an adapter class and an activity, I want to call the activity method from adapter
Adapter
holder.fab_plus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((MainActivity)context).getTotalPrice();
}
});
MainActivity
#Override
public void getTotalPrice() {
Toast.makeText(MainActivity.this, "Your Message Has Been Sent", Toast.LENGTH_SHORT).show();
}
I want to call getTotalPrice method form adapter
Try this:
holder.fab_plus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onClicked.getTotalPrice("Price");
}
});
Your interface in adapter class:
public interface OnClicked {
void getTotalPrice(String price);
}
At the top of your adapter class:
private OnClicked onClicked;
and initialize it in adapter's constructor like:
public MyAdapter(Context context, ...) {
onClicked = (OnClicked) context;
}
Now make your activity implement the interface like:
public class MyActivity extends Activity implements MyAdapter.OnClicked{
...
#Override
public void getTotalPrice(String price) {
//do whatever you like here
}
}
Now its done!
If you are looking for how to write an interface here is what you can do :)
Declare interface in your adapter,
public class YourAdapter extends BaseAdapter {
public interface ClickInformerInterface{
public void getTotalPrice();
}
Declare a property in YourAdapter to hold the reference to class which confirms the interface :)
ClickInformerInterface mInterface;
and in your onclick listener call this :)
holder.fab_plus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mInterface.getTotalPrice();
}
});
In your main activity :) after creating an adapter instance set this as adapter's interface :)
YourAdapter youradapter = new YourAdapter(....)
youradapter.mInterface = this;
Confirm ClickInformerInterface in your mainActivity using,
public class MainActivity extends Activity implements YourAdapter. ClickInformerInterface{
and finally implement method getTotalPrice() in MainActivity :)
public void getTotalPrice() {
Toast.makeText(MainActivity.this, "Your Message Has Been Sent", Toast.LENGTH_SHORT).show();
}
You can use method directly in you adapter class. as like below.
Adapter
holder.fab_plus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getTotalPrice(context);
}
});
Method in adapter class means same class
public void getTotalPrice(Context context) {
Toast.makeText(context, "Your Message Has Been Sent", Toast.LENGTH_SHORT).show();
}
You shouldn't call activity methods from adapter directly. There are several ways to do what you want. Two most popular ways are Interface and EventBus.
I recommend using EventBus, since it's much easier to implement, and requires less code.
In your Activity, create a method that reacts to specific event:
#Subscribe
public void onEvent(MyButtonClickEvent e){
//do stuff
}
In your adapter, send such event:
EventBus.getDefault().post(new MyButtonClickEvent());
Don't forget to register for events in your activity:
onStart/onStop: EventBus.getDefault().register(this)/unregister(this);
For more information, visit EventBus github page: https://github.com/greenrobot/EventBus
You can send broadcast from Adapter and can receive broadcast in Main Activity.
Related
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);
}
}
});
I simplified my code for you to get better understanding it.
I have MyAdapter and MyActivity working both perfectly.
class MyAdapter extends RecyclerView... {
...
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
...
holder.mImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((Listener) context).onSelected(object);
}
});
}
...
}
class MyActivity implements MyAdapter.Listener {
...
#Override
public void onSelected(Object object) {
// do things with object here
}
...
}
I want to make my another activity MyAnotherActivity implement MyAdapter.Listener.
When I run my app, and click on my object, an overriden onSelected() just ignored.
public class MyAnotherActivity implements MyAdapter.Listener {
...
#Override
public void onSelected(Object object) {
Log.e("MyAnotherActivity", "This text doesn't shows");
}
...
}
The used Listener implementation depends on the context parameter passed to MyAdapter constructor. Because on this line ((Listener) context).onSelected(object); you are casting the context field of the MyAdapter class to Listener implementation.
So when you are calling the constructor of the MyAdapter, you need to pass the context of MyAnotherActivity.
public class MyAnotherActivity implements MyAdapter.Listener {
#Override
protected void onCreate(Bundle savedInstanceState) {
...
MyAdapter adapter = new MyAdapter(this /*Context of MyAnotherActivity*/, ...);
...
}
}
If you want to implement any methods inside of any class (not just activity) , you can use EventBus, a lightweight library for passing messages and events around.
It's very easy to implement and the code samples will help you out along the way
http://greenrobot.org/eventbus/
I have a Fragment that needs to communicate more than one Action back to it's Activity. For example,
When a button is clicked, it needs to communicate the onClick back to the Activity.
2.When a user's login and password match, a boolean value is sent to the Activity notifying it to start an Intent.
My first question is, is this common where a Fragment needs to relay more that one type of Action back to the Activity? And secondly, how is this solved? Is the following a good way to do it...
I created a custom class, which extends Fragment and included the two interfaces that I need (One to pass the onClick back to the Activity and One to pass a boolean value):
public class CustomInterfaceFragment extends Fragment {
public OnClickedListener listener;
public LogInInterface loggedInListener;
static interface OnClickedListener{
public void buttonClicked(View v);
}
static interface LogInInterface{
public void userLoggedIn(boolean loggedIn);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
this.listener = (OnClickedListener)activity;
this.loggedInListener = (LogInInterface)activity;
}}
I then extended this custom class in my Fragment and used the appropriate methods where needed. This is the onClick method in the Fragment...
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.register_button:{
listener.buttonClicked(v);//***Pass onClick Back to Activity
break;
}
case R.id.fragment_login_loginButton:{
ParseUser.logInInBackground(userName.getText().toString(), password.getText().toString(), new LogInCallback() {
#Override
public void done(ParseUser user, ParseException e) {
if (user!=null){
boolean verified = user.getBoolean("emailVerified");
if(!verified){
Toast.makeText(getActivity(),"Please Verify",Toast.LENGTH_LONG).show();
progressDialog.dismiss();
ParseUser.logOut();
}else{
progressDialog.dismiss();
loggedInListener.userLoggedIn(true);//***Pass boolean Back to Activity
}
}else {
Toast.makeText(getActivity(),e.getMessage(),Toast.LENGTH_LONG).show();
progressDialog.dismiss();
}
}
});
}
break;
}
}
Finally I implemented the custom fragment class and its interfaces in my Activity in order to retrieve the data.
Is this a reasonable way to solve this problem or am I missing something? The application seems to work fine. I just want to know what the best programming practice would be. Thank you.
all i can say is you can bring down this two interfaces to one like this below
public interface fragmentInteractions{
public void OnClickedListener(View v);
public void userLoggedIn(boolean loggedIn);
....
....
}
and i don't think the interface here needs to be static
Elaborating on Avinash Joshi's answer :
public interface CustomListener {
void onButtonClicked();
void onLoginResult( boolean isUserLoggedIn ); // You can pass User object via this method in case its required to do some operations
}
public class MainActivity extends Activity implements CustomListener {
#Override
public void onCreate( Bundle savedInstance ) {
// Initialize UI elements
// Initialize Fragment
}
#Override
public void onButtonClicked() {
//Action to be performed on button click
}
#Override
public void onLoginResult( boolean isUserLoggedIn ) {
if( isUserLoggedIn ) {
//take user to dashboard or any other screen
//Usually with the help of SupportFragmentManager
}
else {
//Take user to signup screen with an optional toast message
//In case parameters like User name and password need not be entered by user again, you can access them as function parameters and pass them to signupFragment via bundle
}
}
}
public class LoginFragment extends Fragment {
CustomListener mCustomListener;
#Override
public void onAttach( Context context ) {
super.onAttach( Context context );
try {
mCustomListner = (CustomListener) context;
} catch ( ClassCastException e {
Log.e(TAG, "Activity must implement CustomListener")
}
}
//Rest of Fragment initialization code here
}
Here's a complete example :
http://www.truiton.com/2015/12/android-activity-fragment-communication/
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