Reputation: 4482
I am trying to have the button's text change on a button click in the list view, and I tried doing it through the custom adapter. With logs the onclick is called just the text does not seem to change:
This is my adapter code:
public class UserViewerAdapter extends BaseAdapter {
public List<DatabaseUser> _list;
public List<UserResponse> _listForSearch;
private final Activity mContext;
private ConfirmManager confirmManager;
private int query;
private Button isFriend;
// database helper
private DatabaseHelper db;
private static LayoutInflater inflater = null;
public UserViewerAdapter(Activity context, List<DatabaseUser> list) {
mContext = context;
_list = list;
//establishing db
db = new DatabaseHelper(mContext);
confirmManager = new ConfirmManager();
query = 0;
}
public UserViewerAdapter( List<UserResponse> list, Activity context) {
mContext = context;
_listForSearch = list;
query = 1;
//establishing db
db = new DatabaseHelper(mContext);
confirmManager = new ConfirmManager();
}
@Override
public int getCount() {
if(query == 0) {
return _list.size();
}
return _listForSearch.size();
}
@Override
public Object getItem(int position) {
if(query == 0) {
return _list.get(position);
}
return _listForSearch.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater inflater = mContext.getLayoutInflater();
v = inflater.inflate(R.layout.users_layout, null);
}
ImageView userImage = (ImageView) v.findViewById(R.id.userImage);
TextView text = (TextView) v.findViewById(R.id.label);
isFriend = (Button) v.findViewById(R.id.btnFriend);
String isFriendText;
//coming from search
if(query == 1) {
if (_listForSearch != null && _listForSearch.size() > 0) {
text.setText(_listForSearch.get(position).getName());
}
Picasso.with(mContext).setLoggingEnabled(true);
// String pictureToAdd = Constants.USER_IMAGES + _listForSearch.get(position).getPicId();
// String photo = _listForSearch.get(position).get_picture();
// Log.d(Constants.DEBUG, "THE photo IS " + photo);
// Log.d(Constants.DEBUG, "THE constant IS " + Constants.USER_IMAGES);
// if (photo.equals("default.jpg")) {
Picasso.with(mContext).load(R.drawable.default_profile_image).resize(50, 50).into(userImage);
isFriendText = "Add Friend";
if(_listForSearch.get(position).isFriend()) {
isFriendText = "Remove Friend";
}
isFriend.setText(isFriendText);
final String finalIsFriendText = isFriendText;
isFriend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Remove friend
callConfirmAddOrRemove(_listForSearch.get(position), finalIsFriendText);
Log.d(Constants.DEBUG, "clicked friend button " + finalIsFriendText);
}
});
}
return v;
}
private void changeText(String finalIsFriendText) {
String newTextToFill = "";
if(finalIsFriendText.equals("Remove Friend")) {
newTextToFill = "Add Friend";
}
if(finalIsFriendText.equals("Add Friend")) {
newTextToFill = "Remove Friend";
}
Log.d(Constants.DEBUG, "changing text of friend button " + newTextToFill);
isFriend.setText(newTextToFill);
notifyDataSetChanged();
}
private void callConfirmAddOrRemove(UserResponse userResponse, String finalIsFriendText) {
boolean dlg = confirmManager.Confirm(mContext, mContext.getString(R.string.remove_friend), mContext.getString(R.string.details_confirmation)
+ "\n" + mContext.getString(R.string.details_info),
mContext.getString(R.string.submit), mContext.getString(R.string.cancel), addOrRemove(userResponse, finalIsFriendText),
cancelPost());
}
private Runnable addOrRemove(final UserResponse userResponse, final String finalIsFriendText) {
return new Runnable() {
public void run() {
sendToDb(userResponse, finalIsFriendText);
}
};
}
private void sendToDb(UserResponse userResponse, String finalIsFriendText) {
Log.d(Constants.DEBUG, "sending to db friend change");
String uid, name, picid;
int points, totalshifts, totalhours, isguarding, isfriend;
uid = userResponse.getUserId();
name = userResponse.getName();
picid = userResponse.getPictureId();
points = userResponse.getTotalPoints();
totalshifts = userResponse.getTotalShifts();
totalhours = userResponse.getTotalHours();
isguarding = 0;
if(userResponse.isCheckedIn()) {
isguarding = 1;
}
//have to do the opposite since trying to add or remove 3 means newly added friend, 2 means newly removed friend
isfriend = 3;
if(userResponse.isFriend()) {
isfriend = 2;
}
DatabaseUser addOrRemoveUser = new DatabaseUser(uid, name, picid, points, totalshifts,totalhours, isguarding, isfriend);
db.updateFriend(addOrRemoveUser);
changeText(finalIsFriendText);
notifyDataSetChanged();
}
private Runnable cancelPost() {
return new Runnable() {
public void run() {
Log.d(Constants.DEBUG, "Canceled posting item");
}
};
}
}
This is the xml (I set android focusable to false for the listview on itemclick to work):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dip" >
<!-- ListRow Left side Thumbnail image -->
<LinearLayout android:id="@+id/thumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dip"
android:layout_alignParentLeft="true"
android:layout_marginRight="5dip">
<ImageView
android:id="@+id/userImage"
android:layout_width="50dip"
android:layout_height="50dip"
android:focusable="false"
android:focusableInTouchMode="false"/>
</LinearLayout>
<!-- Name-->
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/thumbnail"
android:layout_centerInParent="true"
android:layout_marginLeft="25dip"
android:textColor="#040404"
android:typeface="sans"
android:textSize="15dip"
android:textStyle="bold"
android:text="DEFAULT NAME"
android:focusable="false"
android:focusableInTouchMode="false"/>
<!-- Friend button -->
<Button android:id="@+id/btnFriend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/friends"
android:layout_marginRight="5dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:textSize="15dip"
android:focusable="false"
android:focusableInTouchMode="false"/>
</RelativeLayout>
Upvotes: 0
Views: 59
Reputation: 11597
In the click listener of getView
, the method:
callConfirmAddOrRemove(_listForSearch.get(position), finalIsFriendText);
you could not get right position
, so you have to define a final position
, or binding a position
tag with the button isFriend
.
[UPDATE]
isFriend.setTag(position); //this is inside getView
and then in your listener:
int position = (int)v.getTag(); //this position will be correct one
Hope this help!
Upvotes: 1
Reputation: 580
I think the problem is that isFriend
being used to update text, use another to do this operation.
And also notice the UI Main Thread problem.
private Button btnToUpdate;
@Override
public void onClick(View v) {
btnToUpdate = v; //save which button to update
//Remove friend
callConfirmAddOrRemove(_listForSearch.get(position), finalIsFriendText);
Log.d(Constants.DEBUG, "clicked friend button " + finalIsFriendText);
}
private void changeText(String finalIsFriendText) {
String newTextToFill = "";
if(finalIsFriendText.equals("Remove Friend")) {
newTextToFill = "Add Friend";
}
if(finalIsFriendText.equals("Add Friend")) {
newTextToFill = "Remove Friend";
}
Log.d(Constants.DEBUG, "changing text of friend button " + newTextToFill);
btnToUpdate.setText(newTextToFill); //use btnToUpdate to update text
notifyDataSetChanged();
}
Upvotes: 0
Reputation: 59274
You are trying to change the text in a separate thread, however, only the UI Main Thread can change Views like TextViews and Buttons.
To work it out, you can use runOnUiThread
runOnUiThread(new Runnable() {
public void run() {
// Update Button Text
}
});
So, in sendToDB
, change
changeText(finalIsFriendText);
for
runOnUiThread(new Runnable() {
public void run() {
changeText(finalIsFriendText);
}
});
runOnUIThread
is a method from java.lang.Runnable as can be seen in the Docs
Runs the specified action on the UI thread. If the current thread is the UI thread, then the action is executed immediately. If the current thread is not the UI thread, the action is posted to the event queue of the UI thread.
So it is a function that takes the Runnable you input as parameter, and run it in the UI Thread, making it possible to change UI elements inside any other threads.
Upvotes: 1