'Android Studio - how to update Fragment's UI onButtonClick in a listview using BaseAdapter
The structure:
(1) Activity's FrameLayout -> (2) Fragment's ListView -> (3) Base Adapter
There are buttons such as like and reply in every row in the layout.
Whenever user hits the like button, I will have to change a TextView's text in the (1) Activity.
I couldn't find a solid answer thru searching.
So
I want communication between Adapter and Fragment.
Button click in BaseAdapter -> update UI in Activity(which contains fragment)
public class ForumDetailCommentFragment extends Fragment {
private static final String ARG_COMMENTS = "ARG_COMMENTS";
private ArrayList<Comment> mComments;
public static ForumDetailCommentFragment newInstance(ArrayList<Comment> _comments) {
Bundle args = new Bundle();
args.putSerializable(ARG_COMMENTS, _comments);
ForumDetailCommentFragment fragment = new ForumDetailCommentFragment();
fragment.setArguments(args);
return fragment;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mComments = (ArrayList<Comment>) getArguments().getSerializable(ARG_COMMENTS);
organizeComments();
// adapter
ListView lv_comments = view.findViewById(R.id.frag_forum_detail_comments_lv);
lv_comments.setAdapter(new CommentAdapter(getActivity(), mComments));
lv_comments.setDivider(null);
}
}
public class CommentAdapter extends BaseAdapter {
public static final String TAG = "ForumAdapter.TAG";
// BASE ID
private static final long BASE_ID = 0x1011;
// reference to our owning screen(context)
private Context mContext;
// reference to our collection
private Comment mComment = null;
private ArrayList<Comment> mCollection;
public CommentAdapter(Context _context, ArrayList<Comment> _collection) {
this.mContext = _context;
this.mCollection = _collection;
}
@Override
public int getCount() {
if(mCollection != null) return mCollection.size();
return 0;
}
@Override
public Object getItem(int position) {
if(mCollection != null && position >= 0 && position < mCollection.size()){
return mCollection.get(position);
}
return null;
}
@Override
public long getItemId(int position) {
return BASE_ID + position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder vh = null;
mComment = (Comment) getItem(position);
if(convertView == null){
convertView = LayoutInflater.from(mContext).inflate(R.layout.lv_comment_layout, parent, false);
vh = new ViewHolder(convertView);
convertView.setTag(vh);
}else{
vh = (ViewHolder) convertView.getTag();
}
if( mComment != null){
// vh.tv_filter_league.setFocusable(false);
// vh.tv_filter_league.setFocusableInTouchMode(false);
// vh.tv_filter_category.setFocusable(false);
// vh.tv_filter_category.setFocusableInTouchMode(false);
// TODO: loop through user's like list.
// TODO: if contains, change the icon's color
if(mComment.getLayer() == 0) vh.child_divider.setVisibility(View.GONE);
else vh.child_divider.setVisibility(View.VISIBLE);
vh.iv_emblem.setImageResource(mComment.getAuthorEmblem(mContext));
vh.tv_author.setText(mComment.getAuthorUser().getUName());
vh.tv_timestamp.setText(mComment.getDateTimestamp());
vh.tv_desc.setText(mComment.getMentionId() + mComment.getDesc());
vh.tv_like.setText(String.valueOf(mComment.getLike()));
vh.tv_ycard.setText(String.valueOf(mComment.getYCards()));
vh.btn_reply.setOnClickListener(onReplyTap);
vh.btn_like.setOnClickListener(onLikeTap);
vh.btn_ycard.setOnClickListener(onYCardTap);
}
return convertView;
}
View.OnClickListener onLikeTap = new View.OnClickListener() {
@Override
public void onClick(View view) {
//DBUtil.forum_update_like_on_comment(mContext, UPDATE_LIKE, mComment.getId());
}
};
View.OnClickListener onYCardTap = new View.OnClickListener() {
@Override
public void onClick(View view) {
//DBUtil.forum_update_ycard_on_comment(mContext, UPDATE_LIKE, mComment.getId());
}
};
View.OnClickListener onReplyTap = new View.OnClickListener() {
@Override
public void onClick(View view) {
}
};
static class ViewHolder{
// TODO:
LinearLayout child_divider;
ImageView iv_emblem;
TextView tv_author, tv_timestamp, tv_desc, tv_like, tv_ycard, btn_reply;
ImageButton btn_like, btn_ycard;
public ViewHolder(View _layout){
child_divider = _layout.findViewById(R.id.lv_base_forum_detail_divider_layer_2);
iv_emblem = _layout.findViewById(R.id.lv_base_forum_detail_iv_emblem);
tv_author = _layout.findViewById(R.id.lv_base_forum_detail_tv_uname);
tv_desc = _layout.findViewById(R.id.lv_base_forum_detail_tv_desc);
tv_timestamp = _layout.findViewById(R.id.lv_base_forum_detail_tv_timestamp);
tv_like = _layout.findViewById(R.id.lv_base_forum_detail_tv_like);
tv_ycard = _layout.findViewById(R.id.lv_base_forum_detail_tv_ycard);
btn_reply = _layout.findViewById(R.id.lv_base_forum_detail_btn_reply);
btn_like = _layout.findViewById(R.id.lv_base_forum_detail_btn_like);
btn_ycard = _layout.findViewById(R.id.lv_base_forum_detail_btn_ycard);
}
}
}
Solution 1:[1]
Create an interface like:
public interface Callback {
public void OnFavoriteClicked()
}
And make your fragment implements it. On your adapter, you should create a variable of this interface type (named callback, for example) and reference it from the fragment. From constructor
Adapter adapter = new Adapter(this@Fragment)
or some set method
adapter.setCallback(this)
Later, you can invoke the interface methods from your adapter like this:
callback.OnFavoriteClicked()
And the override method you must implement in the fragment should be called.
Example in Kotlin:
class Adapter() ... {
interface Callback {
fun action()
}
private var callback: Callback? = null
fun setListener(callback: Callback) {
this.callback = callback
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.itemView.setOnClickListener {
callback?.action()
}
}
...
class ExampleFragment : Fragment, Adapter.Callback {
...
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val adapter = Adapter()
adapter.setListener(this)
}
override fun action() {
//Callback from adapter
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
