I have a RecyclerView with multiple TextViews and a Button. The button triggers an animation like the gif below:
I am doing this by creating a RecyclerView.Adapter and creating an OnClickListener like so:
public class recyclerViewAdapter extends RecyclerView.Adapter<recyclerViewAdapter.ViewHolder> {
private ArrayList<MyObject> objects;
// constructor and other stuff ...
public void setDefaultRequestBtnClickListener(View.OnClickListener defaultRequestBtnClickListener) {
this.defaultRequestBtnClickListener = defaultRequestBtnClickListener;
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, int position) {
MyObject object = objects.get(position);
if (object.getRequestBtnClickListener() != null) {
holder.Btn.setOnClickListener(object.getRequestBtnClickListener());
}else {
holder.Btn.setOnClickListener(defaultRequestBtnClickListener);
}
}
public class ViewHolder extends RecyclerView.ViewHolder{
TextView value;
TextView currentVal;
TextView Btn;
ConstraintLayout parent;
public ViewHolder(#NonNull View itemView) {
super(itemView);
value = itemView.findViewById(R.id.totalPrice);
currentVal = itemView.findViewById(R.id.checkBtn);
Btn = itemView.findViewById(R.id.animateBtn);
parent = itemView.findViewById(R.id.parent);
}
public void bind(final OnMyClickListener listener) {
parent.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
listener.onMyClick(v, getLayoutPosition());
}
});
}
}
public interface OnMyClickListener{
void onMyClick(View view, int position);
}
}
this creates and binds a view holder in a recycler view to the TextViews and buttons. At the moment a user has to click the element to activate the Btn and animation. The below is the fragment that is initiating the adapter:
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.frag_object_layout, container, false);
final RecyclerView recyclerView = rootView.findViewById(R.id.list);
final ArrayList<MyObject> objects = MyObject.getTestingList();
final recyclerViewAdapter adapter = new recyclerViewAdapter(objects, getContext());
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
adapter.setDefaultRequestBtnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
recyclerViewAdapter.ViewHolder holder = (recyclerViewAdapter.ViewHolder) recyclerView.findViewHolderForAdapterPosition(Position);
if (holder != null) {
if (holder.value.getAlpha() == 0.0f) {
holder.value.animate().alpha(1.0f).setDuration(500);
holder.value.animate().translationY(-38).setDuration(1000);
holder.checkValue.animate().translationY(38).setDuration(1000);
} else {
holder.value.animate().alpha(0.0f).setDuration(500);
holder.value.animate().translationY(0).setDuration(500);
holder.checkValue.animate().translationY(0).setDuration(500);
}
}
}
});
adapter.setOnMyClickListener(new recyclerViewAdapter.OnMyClickListener() {
#Override
public void onMyClick(View view, int pos) {
Position = pos;
holder = (recyclerViewAdapter.ViewHolder) recyclerView.findViewHolderForAdapterPosition(Position);
}
});
return rootView;
}
}
This is all working great on an emulator, but on an older device the animation is skipping and the views go directly to their final position. Why is that? I checked the processing time and it is below the 16ms threshold.
How can I improve this?
(Posting the whole code is difficult here. ask for code and I will update the question)
The issue here is that I was doing this programmatically. For some reason, if I call Animator object and pass anim xml files then the animation works (on old device). Does anyone know why?
Related
I have a RecyclerView with multiple TextViews and a Button. The button triggers an animation like the gif below:
I am doing this by creating a RecyclerView.Adapter and creating an OnClickListener like so:
public class recyclerViewAdapter extends RecyclerView.Adapter<recyclerViewAdapter.ViewHolder> {
private ArrayList<MyObject> objects;
// constructor and other stuff ...
public void setDefaultRequestBtnClickListener(View.OnClickListener defaultRequestBtnClickListener) {
this.defaultRequestBtnClickListener = defaultRequestBtnClickListener;
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, int position) {
MyObject object = objects.get(position);
if (object.getRequestBtnClickListener() != null) {
holder.Btn.setOnClickListener(object.getRequestBtnClickListener());
}else {
holder.Btn.setOnClickListener(defaultRequestBtnClickListener);
}
}
public class ViewHolder extends RecyclerView.ViewHolder{
TextView value;
TextView currentVal;
TextView Btn;
ConstraintLayout parent;
public ViewHolder(#NonNull View itemView) {
super(itemView);
value = itemView.findViewById(R.id.totalPrice);
currentVal = itemView.findViewById(R.id.checkBtn);
Btn = itemView.findViewById(R.id.animateBtn);
parent = itemView.findViewById(R.id.parent);
}
public void bind(final OnMyClickListener listener) {
parent.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
listener.onMyClick(v, getLayoutPosition());
}
});
}
}
public interface OnMyClickListener{
void onMyClick(View view, int position);
}
}
this creates and binds a viewholder in a recyclerview to the TextViews and buttons. At the moment a user has to click the element to activate the Btn and animation. The below is the Fragment that is initiating the adapter:
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.frag_object_layout, container, false);
final RecyclerView recyclerView = rootView.findViewById(R.id.list);
final ArrayList<MyObject> objects = MyObject.getTestingList();
final recyclerViewAdapter adapter = new recyclerViewAdapter(objects, getContext());
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
adapter.setDefaultRequestBtnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
recyclerViewAdapter.ViewHolder holder = (recyclerViewAdapter.ViewHolder) recyclerView.findViewHolderForAdapterPosition(Position);
if (holder != null) {
if (holder.value.getAlpha() == 0.0f) {
holder.value.animate().alpha(1.0f).setDuration(500);
holder.value.animate().translationY(-38).setDuration(1000);
holder.checkValue.animate().translationY(38).setDuration(1000);
} else {
holder.value.animate().alpha(0.0f).setDuration(500);
holder.value.animate().translationY(0).setDuration(500);
holder.checkValue.animate().translationY(0).setDuration(500);
}
}
}
});
adapter.setOnMyClickListener(new recyclerViewAdapter.OnMyClickListener() {
#Override
public void onMyClick(View view, int pos) {
Position = pos;
holder = (recyclerViewAdapter.ViewHolder) recyclerView.findViewHolderForAdapterPosition(Position);
}
});
return rootView;
}
}
This is all working great on an emulator, but on an older device the animation is skipping and the views go directly to their final position. Why is that? I checked the processing time and it is below the 16ms threshold.
How can I improve this?
(Posting the whole code is difficult here. ask for code and I will update the question)
RecyclerView shows first items after some correct items. And one of incorrect items can change own data several times... It is really strange and i dont know why, in another app i wrote the same code and all works nice. I tried to find the resolve, but did not found nothing what helps. You can see video to understand what is going on.
video
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable
ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_car_list, container, false);
mRecyclerView = view.findViewById(R.id.car_recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
updateUI();
return view;
}
private class CarHolder extends RecyclerView.ViewHolder implements
View.OnClickListener {
private Car mCar;
public CarHolder(#NonNull final View itemView) {
super(itemView);
itemView.setOnClickListener(this);
mProducerTextView = itemView.findViewById(R.id.producerCardTextView);
mModelTextView = itemView.findViewById(R.id.modelCardTextView);
mPriceTextView = itemView.findViewById(R.id.priceCardTextView);
}
public void bind(Car car) {
mCar = car;
mProducerTextView.setText(getString(R.string.producer_params,
mCar.getProducer()));
mModelTextView.setText(getString(R.string.model_params,
mCar.getModel()));
mPriceTextView.setText(getString(R.string.price_params,
mCar.getPrice()));
}
#Override
public void onClick(View v) {
mListCallBack.onCarSelected(mCar);
}
}
private class CarAdapter extends RecyclerView.Adapter<CarHolder> {
private List<Car> mCars;
public CarAdapter(List<Car> cars) {
mCars = cars;
}
#NonNull
#Override
public CarHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
LayoutInflater inflater = LayoutInflater.from(getActivity());
View view = inflater.inflate(R.layout.list_item_car, viewGroup, false);
return new CarHolder(view);
}
#Override
public void onBindViewHolder(#NonNull CarHolder carHolder, int i) {
Car car = mCars.get(i);
carHolder.bind(car);
}
#Override
public int getItemCount() {
return mCars.size();
}
public void setCars(List<Car> cars) {
this.mCars = cars;
}
}
public void updateUI(){
List<Car> cars = CarLab.getCarLab(getActivity()).getCars();
if (mAdapter == null) {
mAdapter = new CarAdapter(cars);
mRecyclerView.setAdapter(mAdapter);
} else {
mAdapter.setCars(cars);
mAdapter.notifyDataSetChanged();
}
}
may be you can try your RecyclerView not to recyle items using:
mRecyclerView.getRecycledViewPool().setMaxRecycledViews(0,0);
in your onCreate() method below mRecyclerView.setLayoutManager(...);
The problem occurs when you use the field variable mCar (which manipulates by all bind events) to update your viewHoleder, just simply use the car variable you pass to the bind to update views.
The other problem with your code is inside onClick, again you should not use the field variable mCar, instead get the item it needs like this:
#Override
public void onClick(View v) {
Car car = mCars.get(getAdapterPosition());
mListCallBack.onCarSelected(car);
}
I have a fragment which must contains two recycler views. The view looks like follows. i need to add an item to the bottom recyclerview from a dialog. L'll post my code for the adapter class and xml. Please guide me to achieve this, a sample or a code is more than welcome.
I've tried to pass the data from the dialog to the second recyclerview but it does not show the added item. Tell me anything i'm doing wrong here. Nothing i tried worked out to update my second recyclerview... :/
My Fragment Class
public class ReceiptFragment extends Fragment { //implements ContReceiptsAdapter.ItemOnClickListener
RecyclerView rv_rceipts, rv_addpayments;
RecyclerView.Adapter mContReceiptsAdapter,mAddPaymentsAdapter;
RecyclerView.LayoutManager mLayoutManager1,mLayoutManager2;
View receipts_view;
private Context mContext;
ContReceiptsAdapter contReceiptsAdapter;
AddPaymentsAdapter addPaymentsAdapter;
//-- items in detailed dialog here
private ArrayList<Contract> contracts;
private ArrayList<AddPayments> payments;
private View linearLayout;
public View mRootView;
public ReceiptFragment() {
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
receipts_view = inflater.inflate(R.layout.fragment_receipt, container, false);
BuildReceiptsRV();
BuildAddedPaymentsRV();
// for setting the first item as default in the list
// onItemClicked(0);
return receipts_view;
}
private void BuildReceiptsRV() {
rv_rceipts = receipts_view.findViewById(R.id.rv_tobe_added);
rv_rceipts.setHasFixedSize(true);
rv_rceipts.setItemAnimator(new DefaultItemAnimator());
mLayoutManager1 = new LinearLayoutManager(getActivity());
rv_rceipts.setLayoutManager(mLayoutManager1);
mContReceiptsAdapter = new ContReceiptsAdapter(getActivity(), ApplicationClass.contractList);
rv_rceipts.setAdapter(mContReceiptsAdapter);
}
private void BuildAddedPaymentsRV() {
rv_addpayments = receipts_view.findViewById(R.id.rv_added);
rv_addpayments.setHasFixedSize(true);
rv_addpayments.setItemAnimator(new DefaultItemAnimator());
mLayoutManager2 = new LinearLayoutManager(getActivity());
rv_addpayments.setLayoutManager(mLayoutManager2);
mAddPaymentsAdapter = new AddPaymentsAdapter(getActivity(),ApplicationClass.paymentList);
rv_addpayments.setAdapter(mAddPaymentsAdapter);
}
//change when click on change on item added to second rv
private void changeLayoutRV() {
linearLayout = mRootView.findViewById(R.id.rv_tobe_added);
if (linearLayout.getVisibility() == View.GONE) {
linearLayout.setVisibility(View.VISIBLE);
} else {
linearLayout.setVisibility(View.GONE);
}
}
}
My Adapter for the First Recyclerview
public class ContReceiptsAdapter extends RecyclerView.Adapter<ContReceiptsAdapter.ReceiptsViewHolder> {
// private static Dialog AddItemDialog;
private ArrayList<Contract> contracts;
private ArrayList<AddPayments> payments = new ArrayList<>();
Context mContext;
String inPending;
//for the details dialog
EditText et_number, contract_id_val, product_type_val, mobile_number_ADialog, et_amount_add;
// ImageView btn_add_item;
//--to set to add item dialog
public TextView contract_number, vehicle_number, contract_number_ADialog, vehicle_number_ADialog;
CheckBox checkbox_pending;
public ContReceiptsAdapter(Context context, ArrayList<Contract> contractList) {
contracts = contractList;
mContext = context;
}
public class ReceiptsViewHolder extends RecyclerView.ViewHolder {
TextView tv_contract, tvVehicleN, tvContractType;
ImageView btn_add_item;
LinearLayout detailsLayout;
public ReceiptsViewHolder(#NonNull final View itemView) {
super(itemView);
detailsLayout = itemView.findViewById(R.id.add_details_item_id);
tv_contract = itemView.findViewById(R.id.tv_contract);
tvVehicleN = itemView.findViewById(R.id.tvVehicleN);
tvContractType = itemView.findViewById(R.id.tvContractType);
btn_add_item = itemView.findViewById(R.id.btn_add_item);
}
}
#NonNull
#Override
public ContReceiptsAdapter.ReceiptsViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.receipt_tobe_added_rv_item, viewGroup, false);
final ReceiptsViewHolder receiptsViewHolder = new ReceiptsViewHolder(view);
//dialog ini
// ShowDetails();
final Dialog detailedDialog = new Dialog(this.mContext);
detailedDialog.setContentView(R.layout.fragment_details);
receiptsViewHolder.detailsLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//click view dto show the detaileds view of the list item
contract_number = detailedDialog.findViewById(R.id.contract_id_val);
vehicle_number = detailedDialog.findViewById(R.id.vehicle_num_val);
contract_number.setText(contracts.get(receiptsViewHolder.getAdapterPosition()).getContractNumber());
vehicle_number.setText(contracts.get(receiptsViewHolder.getAdapterPosition()).getVehicleNumber());
detailedDialog.show();
detailedDialog.setCancelable(true);
// mListener.onItemClicked(contracts.indexOf(v.getTag()));
}
});
return receiptsViewHolder;
}
#Override
public void onBindViewHolder(#NonNull final ContReceiptsAdapter.ReceiptsViewHolder viewHolder, int i) {
viewHolder.itemView.setTag(contracts.get(i));
// Contract currentItem = contracts.get(i);
viewHolder.tv_contract.setText(contracts.get(i).getContractNumber());
viewHolder.tvVehicleN.setText(contracts.get(i).getVehicleNumber());
viewHolder.tvContractType.setText(contracts.get(i).getContractType());
final Dialog AddItemDialog = new Dialog(mContext);
AddItemDialog.setContentView(R.layout.fragment_add_receipt);
viewHolder.btn_add_item.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// ShowDetails();7
contract_number_ADialog = AddItemDialog.findViewById(R.id.contract_id_val_add);
contract_number_ADialog.setText(contracts.get(viewHolder.getAdapterPosition()).getContractNumber());
vehicle_number_ADialog = AddItemDialog.findViewById(R.id.product_type_val_add);
vehicle_number_ADialog.setText(contracts.get(viewHolder.getAdapterPosition()).getVehicleNumber());
mobile_number_ADialog = AddItemDialog.findViewById(R.id.et_number_add);
mobile_number_ADialog.setText(contracts.get(viewHolder.getAdapterPosition()).getMobileNumber());
checkbox_pending = AddItemDialog.findViewById(R.id.checkbox_pending_add);
checkbox_pending.setChecked(Boolean.parseBoolean(contracts.get(viewHolder.getAdapterPosition()).getPendingState()));
Button btn_cancel_receipt = AddItemDialog.findViewById(R.id.btn_cancel_receipt);
Button btn_add_receipt = AddItemDialog.findViewById(R.id.btn_add_receipt);
et_amount_add = AddItemDialog.findViewById(R.id.et_amount_add);
AddItemDialog.show();
AddItemDialog.setCancelable(true);
btn_cancel_receipt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AddItemDialog.dismiss();
}
});
btn_add_receipt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AddData();
//add item to rv2
AddItemDialog.dismiss();
}
});
}
});
}
#Override
public int getItemCount() {
return contracts.size();
}
private void addAnItem(AddPayments payment) {
payments = ApplicationClass.paymentList;
payments.add(payment);
this.notifyDataSetChanged();
}
private void AddData() {
String c_code = contract_number_ADialog.getText().toString();
String c_mobile = mobile_number_ADialog.getText().toString();
String c_amount = et_amount_add.getText().toString();
AddPayments added_payment = new AddPayments(c_amount, c_code, c_mobile, "true");
payments.add(added_payment);
notifyDataSetChanged();
}
}
My Adapter class for the Second Recyclerview
public class AddPaymentsAdapter extends RecyclerView.Adapter<AddPaymentsAdapter.AddPayViewHolder> {
private ArrayList<AddPayments> payments;
Context mContext;
public AddPaymentsAdapter(Context context, ArrayList<AddPayments> addPayments) {
mContext = context ;
payments = addPayments;
}
public class AddPayViewHolder extends RecyclerView.ViewHolder{
TextView tv_contract_d, tv_amount_d, tv_isPending_d, tv_mobile_num_d;
ImageView btn_delete_item;
ConstraintLayout addedPaymentLayout;
public AddPayViewHolder(#NonNull View itemView) {
super(itemView);
addedPaymentLayout = itemView.findViewById(R.id.added_payment_item_id);
tv_contract_d = itemView.findViewById(R.id.tv_contract_d);
tv_amount_d = itemView.findViewById(R.id.tv_amount_d);
tv_isPending_d = itemView.findViewById(R.id.tv_isPending_d);
tv_mobile_num_d = itemView.findViewById(R.id.tv_mobile_num_d);
btn_delete_item = itemView.findViewById(R.id.btn_delete_item);
}
}
#NonNull
#Override
public AddPaymentsAdapter.AddPayViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.receipt_added_rv_item, viewGroup, false);
final AddPayViewHolder addPayViewHolder= new AddPayViewHolder(view);
return addPayViewHolder;
}
#Override
public void onBindViewHolder(#NonNull AddPaymentsAdapter.AddPayViewHolder addPayViewHolder, final int i) {
AddPayments currentItem = payments.get(i);
addPayViewHolder.itemView.setTag(payments.get(i));
addPayViewHolder.tv_contract_d.setText(payments.get(i).getAddContractCode());
addPayViewHolder.tv_isPending_d.setText(payments.get(i).getAddIsPending());
addPayViewHolder.tv_amount_d.setText(payments.get(i).getAddAmount());
addPayViewHolder.tv_mobile_num_d.setText(payments.get(i).getAddMobile());
addPayViewHolder.btn_delete_item.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//delete function
// Toast.makeText(mContext, "clicked delete icon inHoldernAdapter", Toast.LENGTH_SHORT).show();
removeItem(i);
}
});
}
#Override
public int getItemCount() {
return payments.size();
}
private void removeItem(int i) {
payments.remove(i);
this.notifyItemRemoved(i);
}
}
From your code in the adapter for the first recycler view you are using this method AddData(); to add data. But this method adds data to payments which is the list where you hold the data which you want to show in the second recycler view but have no connection to it(it's just a field of the adapter class).
The this.notifyDataSetChanged() notifies the current adapter for a change in data(first recycler view). You will need to add this data to the second recycler view adapter thou. You aren't doing that right now.
So a way would be to create a method inside of the fragment which takes a list of AddPayments as argument and add this data to the second recycler view adapater. It would be something like this:
Fragment method:
public void addSecondRVData(AddPayments itemToAdd) {
mAddPaymentsAdapter.addNewPayment(itemToAdd);
}
Second recycler view method:
public void addData(AddPayments itemToAdd) {
payments.add(itemToAdd);
this.notifyDataSetChanged():
}
Dont forget to initialize the payment list in the second recycler view.
Then in the first adapter do smth like this:
private ReceiptFragment receiptFragment;
//Constructor
public ContReceiptsAdapter(Context context, ArrayList<Contract> contractList, ReceiptFragment receiptFragment) {
contracts = contractList;
mContext = context;
this.receiptFragment = receiptFragment;
}
//Use this to add elements to second rv
receiptFragment.addSecondRVData(newItem);
Hope this helps although is not the cleanest solution. Check the example I wrote here because can't test it at the moment.
In my MainActivity.java I have a sort of button to login. I also have 4 fragments, each of them containing a recycler view (imageview + textview).
The imageview is hidden, but when I press the button it becomes visibile. How can I do that? The notifyDataSetChanged() doesn't work in the adapter and I can't call it on the adapter in the fragment page, because is outside the onCreateView method.
Here's my code:
MainActivity: contains the button
Fragment Page:
public class Classici_Tab extends Fragment {
LinkedList<Book> catalog = new LinkedList<>();
RecyclerView mRecyclerView;
BookListAdapter mAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View fragmentView = inflater.inflate(R.layout.classici_tab, container, false);
fillCatalog("catalog.csv"); //fill the LinkedList
mRecyclerView = (RecyclerView) fragmentView.findViewById(R.id.classici_rv);
mAdapter = new BookListAdapter(getContext(), catalog);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
return fragmentView;
}
}
Adapter:
public class BookListAdapter extends RecyclerView.Adapter<BookListAdapter.BookViewHolder> {
// View Holder
class BookViewHolder extends RecyclerView.ViewHolder
{
public final ImageView cover;
public final TextView title;
public final TextView author;
public final ImageView availability;
final BookListAdapter mAdapter;
public BookViewHolder(View itemView, BookListAdapter adapter) {
super(itemView);
cover = (ImageView) itemView.findViewById(R.id.cover);
title = (TextView) itemView.findViewById(R.id.title);
author = (TextView) itemView.findViewById(R.id.author);
availability = (ImageView) itemView.findViewById(R.id.availability);
MainActivity m = new MainActivity();
if(m.loggedin) availability.setVisibility(View.VISIBLE);
else availability.setVisibility(View.INVISIBLE);
this.mAdapter = adapter;
}
}
private LinkedList<Book> mBookList = new LinkedList<>();
private LayoutInflater mInflater;
boolean isVisible = false;
public BookListAdapter() {}
public BookListAdapter(Context context, LinkedList<Book> bookList) {
mInflater = LayoutInflater.from(context);
this.mBookList = bookList;
}
//IT DOESN'T WORK
public void setPicturesVisibility(boolean isVisible){
this.isVisible = true;
notifyDataSetChanged();
}
#Override
public BookViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View mItemView = mInflater.inflate(R.layout.tab_list_item, parent, false);
return new BookViewHolder(mItemView, this);
}
#Override
public void onBindViewHolder(BookViewHolder holder, int position) {
holder.cover.setImageResource(mBookList.get(position).getCover());
holder.title.setText(mBookList.get(position).getTitle());
holder.author.setText(mBookList.get(position).getAuthor());
holder.availability.setImageResource(mBookList.get(position).getAvailability());
if(isVisible){
holder.availability.setVisibility(View.VISIBLE);
}else{
holder.availability.setVisibility(View.INVISIBLE);
}
}
#Override
public int getItemCount() {
return mBookList.size();
}
}
Not sure why you need to recreate adapter. Without recreating adapter, you can add listener to the button and in the onclick event handler, make image visible in recyclerview adapter's viewholder constructor.
public ViewHolder(View view) {
super(view);
textview = view.findViewById(R.id.textview);
imgView = view.findViewById(R.id.storeImg);
Button button = (Button) view.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
imgView.setVisibility(View.VISIBLE);
}
});
}
You can find recyclerview examples here http://www.zoftino.com/android
There is no need to recreate adapter. You can add a boolean arePicturesVisible = false; in your RecyclerViewAdapter.
And make a method in adapter:
public void setPicturesVisibility(boolean areVisible){
arePicturesVisible = areVisible;
notifyDataSetChanged();
}
Then add:
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
.....
if(arePicturesVisible){
holder.image.setVisibility(View.VISIBLE);
}else{
holder.image.setVisibility(View.INVISIBLE);
}
.....
}
Then in your button onClick() method call setPicturesVisibility() from RecyclerView adapter.
I have two tabs (fragments), NewOrders and FinishedOrders, I'm populating the orders via Volley requests, now each item inside the New Orders tab has a SwipeLayout which show a clickable textview that makes the order finished, and move it to the other tab (backend stuff..), and I got this working perfectly,
The problem is when I click to finish, the recyclerview isn't updated once the request sent successfully, I have to do pull-to-refresh so it would update..! it seems easy to solve, but the issue is handling the swipelayout listener done inside onBindView method inside the adapter..!! that's only place to access it according to the library I'm using (I guess)..! on the other hand refreshing and populating the list happens in the NewOrder tab fragment..!
So how can I make the item to be removed from the list after the click and becomes updated..?!
Any thoughts..!?
My Adapter Class + ViewHolder
Note: the implemented methods in the adapter are required because of the interface of SwipeLayout library
public class OrdersDataAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
implements SwipeAdapterInterface, SwipeItemMangerInterface {
protected SwipeItemRecyclerMangerImpl mItemManger = new SwipeItemRecyclerMangerImpl(this);
public Context context;
ArrayList<OrderPresenter> orders;
public OrdersDataAdapter(ArrayList<OrderPresenter> orders, Context context) {
this.orders = orders;
this.context = context;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.order_card, parent, false);
return new NewOrderVH(v);
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
final OrderPresenter order = this.orders.get(position);
final NewOrderVH vh1 = (NewOrderVH) holder;
vh1.setData(orders.get(position));
mItemManger.bindView(vh1.itemView, position);
vh1.swipeLayout.setShowMode(SwipeLayout.ShowMode.PullOut);
vh1.swipeLayout.addDrag(SwipeLayout.DragEdge.Left,
vh1.swipeLayout.findViewById(R.id.bottom_wrapper));
if (order.isFinished()) {
vh1.swipeLayout.setSwipeEnabled(false);
vh1.setBadge("DONE");
vh1.setBadgeColor(order.getBadgeColor());
} else {
vh1.finish.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// get the clicked item position?
final int position = vh1.getAdapterPosition();
// these responsible for the request which make the order finished
OrderPresenter order = orders.get(position);
OrderRepository.setOrderFinURL(order.getID());
OrderRepository.FinishOrder(order.getID(), context);
/*the commented three lines below didn't help with the problem*/
// notifyItemChanged(position);
// notifyItemRemoved(position);
// notifyDataSetChanged();*/
order.setStatus(order.getStatusText(Order.FINISHED));
}
});
}
}
#Override
public int getItemCount() {
return orders.size();
}
public class NewOrderVH extends RecyclerView.ViewHolder {
SwipeLayout swipeLayout;
private TextView finish;
private CardView orderCard;
TextView Badge;
private ImageView cusPic;
private TextView cusName;
private TextView CusAdress;
private TextView vendorsNum;
private TextView itemsNum;
private TextView time;
private TextView emptyView;
public NewOrderVH(View itemView) {
super(itemView);
Badge = (TextView) itemView.findViewById(R.id.badge);
swipeLayout = (SwipeLayout) itemView.findViewById(R.id.swipe);
finish = (TextView) itemView.findViewById(R.id.finish);
orderCard = (CardView) itemView.findViewById(R.id.OrderCard);
cusPic = (ImageView) itemView.findViewById(R.id.cusPic);
cusName = (TextView) itemView.findViewById(R.id.cusName);
CusAdress = (TextView) itemView.findViewById(R.id.CusAdress);
vendorsNum = (TextView) itemView.findViewById(R.id.vendorsNum);
itemsNum = (TextView) itemView.findViewById(R.id.itemsNum);
time = (TextView) itemView.findViewById(R.id.time);
emptyView = (TextView) itemView.findViewById(R.id.empty_view);
orderCard.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), OrderDetails.class);
v.getContext().startActivity(intent);
}
});
}
public void setData(final OrderPresenter data) {
time.setText(data.getOrderTime());
cusName.setText(data.getFullName());
vendorsNum.setText(data.getVendorsCount());
itemsNum.setText(data.getItemsCount());
CusAdress.setText(data.getFullAddress());
Picasso.with(context).load(data.getCustomerPicture()).into(cusPic);
}
public void setBadgeColor(int drawable) {
this.Badge.setBackgroundResource(drawable);
}
public void setBadge(String badge) {
this.Badge.setText(badge);
}
}
#Override
public int getSwipeLayoutResourceId(int position) {
return R.id.swipe;
}
#Override
public void openItem(int position) {
}
#Override
public void closeItem(int position) {
}
#Override
public void closeAllExcept(SwipeLayout layout) {
}
#Override
public void closeAllItems() {
}
#Override
public List<Integer> getOpenItems() {
return null;
}
#Override
public List<SwipeLayout> getOpenLayouts() {
return null;
}
#Override
public void removeShownLayouts(SwipeLayout layout) {
}
#Override
public boolean isOpen(int position) {
return false;
}
#Override
public Attributes.Mode getMode() {
return null;
}
#Override
public void setMode(Attributes.Mode mode) {
}
}
My NewOrder Fragment
Note: the FinishedOrders tab (fragment) does the same thing as new order but filters the current the Finished status.
public class NewOrdersTab extends Fragment {
RecyclerView recyclerView;
OrdersDataAdapter adapter;
private SwipeRefreshLayout swiperefresh;
private TextView emptyView;
ArrayList<OrderPresenter> modelData;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.new_orders_tab_frag, container, false);
modelData = new ArrayList<>();
recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
swiperefresh = (SwipeRefreshLayout) rootView.findViewById(R.id.swiperefresh);
recyclerView.setLayoutManager(new LinearLayoutManager(this.getActivity()));
swiperefresh.setColorSchemeResources(R.color.colorPrimary, R.color.color_error, R.color.colorInfo);
adapter = new OrdersDataAdapter(modelData, getActivity());
emptyView = (TextView) rootView.findViewById(R.id.empty_view);
recyclerView.setAdapter(adapter);
adapter.setMode(Attributes.Mode.Single);
OrderRepository.fetchOrders("awaiting-shipment", getActivity(), new DataFetch() {
#Override
public void onResponse(ArrayList<OrderPresenter> data) {
swiperefresh.setRefreshing(true);
if (data.size() != 0) {
swiperefresh.setRefreshing(true);
emptyView.setVisibility(View.GONE);
modelData.clear();
modelData.addAll(data);
adapter.notifyDataSetChanged();
} else {
emptyView.setVisibility(View.VISIBLE);
emptyView.setText(getString(R.string.No_New_Orders));
}
swiperefresh.setRefreshing(false);
}
});
return rootView;
}
}
I figured it out, I just added these two lines after I make the request..!
orders.remove(position);
notifyItemRemoved(position);
//notifyDataSetChanged(position);