I am trying to implement different click event listeners for different sections of a single row of listview.
For example:
I have made 2 different linear layouts for the 2 different sections. Any particular way to implement the onclick listeners for the 2 different layouts?
Please suggest any other process of doing this if you have in your mind.
P.S. I cannot define click events in the custom adapter, as the Activity needs to fire the events from it with adding some data to it.
create static method in your Activity :
public static void YourMethod()
{
}
create onClickListener in adapter and call activity method.
holder.YourLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
YourActivity.YourMethod();
}
});
You can implement click Listeners in your adapter class like this-
layout1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
layout2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
Related
My question may seem special but I need your help with how I create dialog boxes for each element of a recyclerview.
Indeed my fragment contains a recycle view with X elements, and I want that, when the user presses one of the elements for a long time, a dialog box opens and asks him "Are you sure you want to delete this element?" and two buttons "Yes" and "Cancel".
I have succeeded in doing so, but I especially want to know if my way of doing it is the right way, in order to avoid acquiring bad programming reflexes.
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
PlaceViewHolder Pholder =(PlaceViewHolder) holder;
Glide.with(mContext)
.load(mPhotoList.get(position))
.fitCenter()
.into(((PlaceViewHolder) holder).mPlace);
Pholder.mPlace.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
switchContext(mPhotoList.get(position));
}
});
Pholder.mPlace.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
new MaterialAlertDialogBuilder(mContext)
.setTitle(R.string.profile_photos_dialog_box_title)
.setMessage(R.string.profile_photos_dialog_box_message)
// Specifying a listener allows you to take an action before dismissing the dialog.
// The dialog is automatically dismissed when a dialog button is clicked.
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Continue with delete operation
}
})
// A null listener allows the button to dismiss the dialog and take no further action.
.setNegativeButton(android.R.string.no, null)
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
return true;
}
});
}
As you can see, every time I call onBindViewHolder I add an onClick listen and it is in this last one that I create the dialog box
Moreover, since my message is always the same, should I turn to a contextmenu, even if I find the format of this menu not very adapted to the choices and possible action?
I'm honestly not sure what the "best practice" may be, but I've done this before. How I've done it is, instead of creating the dialog and performing the action inside the longclick handler within onBindViewHolder, I create a custom listener interface so I can pass
relevant data back to the caller. Like this:
MyListListener
public interface MyListListener {
// Where "index" can be the index of the item, or the object represented by the list item at "index"
void onItemLongPressed(int index);
}
I'll pass that into the constructor of my custom RecyclerView.Adapter like this:
MyAdapter
public class MyAdapter extends ... {
private MyListListener listener;
public MyAdapter(MyListListener listener) {
this.listener = listener;
}
}
Then inside onBindViewHolder
MyAdapter / ViewHolder onBindViewHolder
Pholder.mPlace.setOnLongClickListener(new
View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
listener.onItemLongPressed(position);
}
});
And then my fragment or activity will implement the listener interface:
MyActivity
public class MyActivity extends ... implements MyListListener {
#Override
public void onItemLongPressed(int index) {
// Show the dialog and do things
}
}
I personally like this because it means my adapters are more isolated. They don't do much outside of showing a list of things. The logic behind those "things" ultimately lives elsewhere. It's easier to unit test this way as well, because you can mock the listener interface.
I implemented a RecyclerView which is populating some records
It is populating appointments and appointments have approved and not approved status.
I implemented an approved button so that onclick the approved status for that appointment is updated on the database and also icon and text is changed of that particular displayed record.
but for some reason in onclick when i am updating the text and icon it is not changing dynamically, but the request to database is working since i can see the change in database, and when i reload the whole data set it shows the changes appropriately.
Here is the code
#Override
public void onBindViewHolder(final AppointmentsHolder holder, final int position) {
final AppointmentObject appointment = appointmentList.get(position);
//binding the data with the viewholder views
holder.patient_name.setText(appointment.patient_name);
holder.app_date.setText(appointment.appointment_date);
if (appointment.descr.length() > 30){
holder.app_descr.setText(String.valueOf(appointment.descr.substring(0,30)));
}else {
holder.app_descr.setText(String.valueOf(appointment.descr));
}
if (appointment.approved_status.equals("0")){
holder.approved_status.setTextColor(Color.RED);
holder.approved_status.setText("Not Approved");
holder.app_pa_approve.setImageResource(R.mipmap.approveicon);
}else {
holder.app_pa_approve.setImageResource(R.mipmap.approvedicon);
holder.approved_status.setTextColor(Color.GREEN);
holder.approved_status.setText("Approved");
}
holder.app_pa_relative.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mOnClickListenr.clicked_On_appointment(appointment);
}
});
holder.app_pa_approve.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.approved_status.setTextColor(Color.GREEN);
holder.approved_status.setText("Approved");
holder.app_pa_approve.setImageResource(R.mipmap.approvedicon);
notifyDataSetChanged();
mOnClickListenr.aprove_appointment(appointment, position);
}
});
}
Here is the onBindViewHolder where i am trying to change the data dynamically onclick.
mOnclickListiner.aprove.appointment is just a listiner which i am implementing in the activity to pass data to activity
public interface OnClickListener{
public void clicked_On_appointment(AppointmentObject appointment);
public void aprove_appointment(AppointmentObject appointment, int position);
}
The mOnClickListenr.aprove_appointment(appointment, position); inside the OnClcick is executing so i know that the setText and setImageResource are executing as well but for some reason change in not showing in the view.
As you can see i am using notifyDataSetChanged(); properly.
What might be the cause of this behavior ?
As you can see even when i am clicking on the imageButton no dynamic change
only when i reload the arraylist it shows the changed, which means change is happening in database and onclick is executing
You have to set approved on the appointment When you call notifiyDataSetChanged it is rebinding all the views and the appointment is still marked unapproved
holder.app_pa_approve.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
appointment.setApprovedStatus(1);
holder.approved_status.setTextColor(Color.GREEN);
holder.approved_status.setText("Approved");
holder.app_pa_approve.setImageResource(R.mipmap.approvedicon);
notifyDataSetChanged();
mOnClickListenr.aprove_appointment(appointment, position);
}
});
I have an app that consists of 3 Activities
MainActivity
CalculatorActivity
InformationActivity
My MainActivity has a confirm button that onClick starts the CalculatorActivity and everything is done correct and working as intended.
CalculatorActivity has 2 buttons, one calculateButton that checks something and shows a message and a learnMorebutton that starts the InformationActivity.
When I am on the
CalculatorActivity for the first time everything is fine and working.Pressing the learnMoreButton navigates me to the InformationActivity.That activity looks like this :
InformationActivity:
goBackButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
switchActivity();
}
});
}
public void switchActivity(){
final Intent intentObj = new Intent(this,CalculatorActivity.class);
startActivity(intentObj);
}
A goBack button that gets me back to CalculatorActivity.Going back seems to break the functionality.Although the layout is there and everything looks as it should be, pressing the buttons (calculateButton,learnMoreButton) does nothing.
CalculatorActivity :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calculator);
final Button calculateButton = (Button) findViewById(R.id.calculateId);
final Button learnMoreButton = (Button) findViewById(R.id.learnMoreButtonId);
there are some more TextView and EditText that dont show up here but you get the point.Some more methods that do the calculations ,getters and setters.
This method
public void switchActivity(){
final Intent intentObj = new Intent(this,Information_activity.class);
startActivity(intentObj);
}
But I am not using onResume() , onPause() or any methods from the lifecycle apart from onCreate().
From some search that I have done I found out that I am doing something wrong with how I manage the activity lifecycle but I still can't find the solution.The dev documents didn't help me that much and a post with kinda the same problem as mine is old.
My question is, how the navigation from InformationActivity to CalculatorActivity should be done, so the functionality doesn't break when CalculatorActivity comes back to interact with the user.Which method should be called onResume()? , onRestart()? and how should it look like?
Thanks anyone who is willing to help.
P.S: As I mentioned , I have read the documents for the lifecycle of an Activity but I haven't found the solution.
instead of starting new activity everytime, finish the informationactivity.
goBackButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
You are creating too much activities moving going back and forth this way. You can use either destroy the activity with finish(); or you can also go back to previous activity using onBackPressed();
goBackButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onBackPressed();
}
});
Try this out
goBackButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
InformationActivity.this.finish();
}
});
}
Instead of saying where to go back, you can just finish the activity and it will automatically switch you to the previous one.
I think your activities are hierarchical thus you should be able to do the following from your main calculator activity:
Intent i = new Intent(this, InformationActivity.class);
startActivityForResult(i);
Your back button add this code:
goBackButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setResult(Result.OK);
finish();
}
});
You are all suggesting the same thing.Adding
Information_Activity.this.finish()
fixed the broken functionality , though you are all correct I can pick only one answer.
Thanks
I don't understand why I have to implement the OnClickListener to use the OnClick-method. Assuming this code:
public class KlickitestActivity extends Activity implements OnClickListener {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
#Override
public void onClick(View v) {
// code what happens when a click is made
}
From the class OnClickListener I only use the method onClick(View v) - and this one is overwritten. Why can't I just define the onClick-method without implementing the OnClickListener?
You can. You can do that by using an Anonymous Inner Class :
Button1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
//Do stuff
}});
Button2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
//Do stuff
}});
However implementing an OnClickListener makes it easier to handle events, and improves code readability. i.e You can use one Listener method, and passing a View to handle multiple buttons/listeners with a switch statement, something similar to :
public void onClick(View view){
switch(view.getId()){
case R.id.Button1:
//Stuff for button 1
break;
case R.id.Button2:
//Stuff for button 2
break;
break;
case R.id.Button3:
//Stuff for button 3
break;
}
Just to expand on Mob's answer and also Scott's comment and link...
An Activity is primarily a framework for a UI and as such has no pre-defined way of interacting with a user. As designers / developers we choose which UI components we want the Activity to contain based on the purpose of the Activity.
The UI components such as Buttons, CheckBoxes, ListViews and so on, serve very different purposes and it is not the place of an Activity in it's basic form to know what events those UI elements react to (click, long-click, swipe etc) simply because there is no pre-defined set of UI elements that an Activity will always host. As such it is our responsibility to implement the event handlers (listeners) that we need to use based on how we design the UI.
I have an android program where I have multiple buttons using the same OnClickListener, and I want to be able to reference the button's dynamically assigned text from inside the listener. Is there some way to reference the button that was pushed to get its text? I don't want to have to make multiple button-specific listeners that do the same thing.
In your onClick(View v) you can cast it to a button:
#Override
public void onClick(View v) {
Button clickedButton = (Button)v;
// do stuff with it here.
}
use the View which comes as the argument to the onClick(View v)
this can be casted to a button & worked with.
The argument to onClick is the View that originated the click, which will be the button to which you attached the listener. Cast it to Button to get the button object.
Yes, there should be a way.
public abstract void onClick (View v)
You'll notice that the View that was clicked is passed into the onClick() method. So if you have a reference to the View (Button) available (for example, as an instance variable in the Activity) then you can do this:
public abstract void onClick (View v) {
if (v == firstButton) {
//Do some stuff
}
else if (v == secondButton) {
//Do some other stuff
}
}