Animation on notifyDataSetChanged() in FragmentStatePagerAdapter - android

By overwriting getItemPosition() method I can refresh my FragmentStatePagerAdapter, which works fine. But the change of the contents is not nice to see.
Is there possibility to apply any kind of animation as I refresh the FragmentStatePagerAdapter?

I was also facing same issue.So, what should you do. Make global variables in your adapter for what you want continuous animate.
Now when you start animation on button click. Pass value to global variables.
When you notifydatasetchanged it doesn't effect your animation.
I haven't found any correct way. So, did this thing.It's working perfect.
public class HomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context mContext;
private ArrayList<Response.DataBean> feedArrayList = new ArrayList<>();
FeedClickListener mListener;
#Inject
ImageUtility mImageUtility;
#Inject
AppUtils mAppUtils;
#Inject
PreferenceManager mPref;
private float prevPosition = -1;
private YoYo.YoYoString ropeText,ropeImage;
private int tempHandlePlayPause = 0;
private TextView tempTextView;
private ImageView tempImageView;
/**
* click listeners
*/
interface FeedClickListener {
void onPlayAudioClicked( FeedResponse.DataBean feedItem, SeekBar audioProgress, int position);
void onPauseAudioClicked(FeedResponse.DataBean feedItem);
}
public HomeAdapter(Context context, ArrayList<Response.DataBean> mDataArrayList, HomeClickListener mFeedListener) {
((BaseApplication) context.getApplicationContext()).getAppComponent().inject(this);
this.mContext = context;
this.feedArrayList = mDataArrayList;
mListener = mFeedListener;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ItemViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false));
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
ItemViewHolder holderItem = (ItemViewHolder) holder;
int adapterPosition = holder.getAdapterPosition() - 1;
holderItem.normalContainer.setVisibility(View.VISIBLE);
holderItem.bannerContainer.setVisibility(View.GONE);
setUpNormalItem(adapterPosition, holderItem);
}
}
private void setUpNormalItem(int adapterPosition, ItemViewHolder holder) {
FeedResponse.DataBean feedItem = feedArrayList.get(adapterPosition);
// set up data to current view holder items
setUpItems(holder, feedItem, adapterPosition);
}
private void setUpItems(ItemViewHolder holder, FeedResponse.DataBean feedItem, int position) {
if (feedItem.isstop()) {
holder.playImageView.setVisibility(View.GONE);
holder.pauseImageView.setVisibility(View.VISIBLE);
} else {
holder.playImageView.setVisibility(View.VISIBLE);
holder.pauseImageView.setVisibility(View.GONE);
holder.audioProgress.setProgress(0);
}
holder.playImageView.setOnClickListener(v -> {
feedItem.setIscomplete(false);
if (prevPosition >= 0) {
feedArrayList.get((int)prevPosition).setIsstop(false);
feedArrayList.get((int)prevPosition).setIsPrepare(false);
}
feedArrayList.get(position).setIsstop(true);
feedArrayList.get(position).setIsPrepare(true);
mListener.onPlayAudioClicked(feedItem, holder.audioProgress, position);
prevPosition = position;
tempHandlePlayPause = 1;
tempTextView = holder.tvPlayingBlink;
tempImageView = holder.pauseImageView;
notifyDataSetChanged();
});
holder.pauseImageView.setOnClickListener(v -> {
feedArrayList.get(position).setIsstop(false);
tempTextView = holder.tvPlayingBlink;
tempImageView = holder.pauseImageView;
tempHandlePlayPause = 0;
mListener.onPauseAudioClicked(feedItem);
notifyDataSetChanged();
});
if (feedItem.isPrepare()) {
holder.tvPlayingBlink.setVisibility(View.VISIBLE);
if (tempHandlePlayPause == 1){
startAnimation();
}else {
stopAnimation();
}
} else {
holder.tvPlayingBlink.setVisibility(View.INVISIBLE);
if (tempHandlePlayPause == 1){
startAnimation();
}else {
stopAnimation();
}
}
// play on complete audio
if (feedItem.iscomplete()) {
holder.playImageView.setVisibility(View.VISIBLE);
holder.pauseImageView.setVisibility(View.GONE);
}
if ((!feedItem.iscomplete()) && feedItem.getTotalLength() > 0) {
holder.audioProgress.setMax(feedItem.getTotalLength());
holder.audioProgress.setProgress(0);
}
}
private void startAnimation(){
if (ropeText != null || ropeImage != null) {
ropeText.stop(true);
ropeImage.stop(true);
}
ropeText = YoYo.with(Techniques.Pulse)
.duration(800)
.repeat(YoYo.INFINITE)
.pivot(YoYo.CENTER_PIVOT, YoYo.CENTER_PIVOT)
.interpolate(new AccelerateDecelerateInterpolator())
.playOn(tempTextView);
ropeImage = YoYo.with(Techniques.Pulse)
.duration(800)
.repeat(YoYo.INFINITE)
.pivot(YoYo.CENTER_PIVOT, YoYo.CENTER_PIVOT)
.interpolate(new AccelerateDecelerateInterpolator())
.playOn(tempImageView);
}
private void stopAnimation(){
if (ropeText != null || ropeImage != null) {
ropeText.stop(true);
ropeImage.stop(true);
}
}
public void updateData(List<FeedResponse.DataBean> items) {
feedArrayList.clear();
feedArrayList.addAll(items);
notifyDataSetChanged();
}
public void deleteItem(int position) {
feedArrayList.remove(position);
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return (feedArrayList.size());
}
public static class ItemViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.image_view_3)
ImageView imageView3;
#BindView(R.id.tvplayingblink)
TextView tvPlayingBlink;
public ItemViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}

Related

Problem of automatic change of data value when scrolling in RecyclerView

I have attached a picture to help you understand my problem.
I'm making an Workout app.
When the button is pressed, the routine is added
In the added routine, it can use the button again to add detailed data (set, lbs, reps).
So, I am using a two type RecyclerView (except footer).
I used DiffUtil to update the items being added.
I found a strange phenomenon while experimenting for testing. (See photo)
It wasn't an error, so I can't figure out what's wrong with it.
After entering the data, when i added a number of detailed items, the value of the data entered first appeared in the items added later.
And if i scrolled after many items were added, the data moved randomly.
However, what is expected is this phenomenon when you add a lot of items or scroll.
What's wrong?
RoutineAdapter.java
public class RoutineAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
final static int TYPE_ROUTINE = 1;
final static int TYPE_ROUTINE_DETAIL = 2;
final static int TYPE_ROUTINE_FOOTER = 3;
private Context context;
private List<Object> mItems = new ArrayList<>();
OnRoutineItemClickListener routinelistener;
OnRoutineAddClickListener routineAddListener;
public void updateRoutineList(List<Object> newRoutineList) {
final RoutineDiffUtil diffCallback = new RoutineDiffUtil(this.mItems, newRoutineList);
final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);
this.mItems.clear();
this.mItems.addAll(newRoutineList);
diffResult.dispatchUpdatesTo(this);
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
context = parent.getContext();
View itemView;
if(viewType == TYPE_ROUTINE){
itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.routine_item, parent, false);
return new RoutineViewHolder(itemView);
}
else if(viewType == TYPE_ROUTINE_DETAIL){
itemView = LayoutInflater.from(context).inflate(R.layout.routine_detail_item, parent, false);
return new RoutineDetailViewHolder(itemView);
}
else {
itemView = LayoutInflater.from(context).inflate(R.layout.add_routine_item, parent, false);
return new RoutineAddFooterViewHolder(itemView);
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
Object obj;
switch (getItemViewType(position)) {
case TYPE_ROUTINE:
obj = mItems.get(position);
setRoutineData((RoutineViewHolder) holder, (RoutineModel) obj);
break;
case TYPE_ROUTINE_DETAIL:
obj = mItems.get(position);
RoutineDetailModel item = (RoutineDetailModel) obj;
((RoutineDetailViewHolder) holder).setDetailItem(item);
break;
case TYPE_ROUTINE_FOOTER:
break;
}
}
#Override
public int getItemCount() {
if(mItems == null)
return -1;
return mItems.size() + 1; // for footer
}
#Override
public int getItemViewType(int position) {
if(position == mItems.size()) {
return TYPE_ROUTINE_FOOTER;
}
else {
Object obj = mItems.get(position);
if(obj instanceof RoutineModel) {
return TYPE_ROUTINE;
}
else {
// obj instanceof RoutineDetailModel
return TYPE_ROUTINE_DETAIL;
}
}
}
// add routine interface
public interface OnRoutineAddClickListener {
public void onAddRoutineClick();
}
public void setOnAddRoutineClickListener(OnRoutineAddClickListener listener) {
this.routineAddListener = listener;
}
// details add / remove interface
public interface OnRoutineItemClickListener {
public void onAddBtnClicked(int curRoutinePos);
public void onDeleteBtnClicked(int curRoutinePos);
public void onWritingCommentBtnClicked(int curRoutinePos);
}
public void setOnRoutineClickListener(OnRoutineItemClickListener listener) {
this.routinelistener = listener;
}
private class RoutineViewHolder extends RecyclerView.ViewHolder {
public TextView routine;
public Button addSet;
public Button deleteSet;
public Button comment;
public RoutineViewHolder(#NonNull View itemView) {
super(itemView);
initViews();
addSet.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(routinelistener != null && getAdapterPosition() != RecyclerView.NO_POSITION)
routinelistener.onAddBtnClicked(getAdapterPosition());
}
});
deleteSet.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(routinelistener != null && getAdapterPosition() != RecyclerView.NO_POSITION)
routinelistener.onDeleteBtnClicked(getAdapterPosition());
}
});
comment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(routinelistener != null && getAdapterPosition() != RecyclerView.NO_POSITION)
routinelistener.onWritingCommentBtnClicked(getAdapterPosition());
}
});
}
}
private class RoutineDetailViewHolder extends RecyclerView.ViewHolder {
public TextView set;
public TextView weight;
public RoutineDetailViewHolder(#NonNull View itemView) {
super(itemView);
initViews();
}
private void initViews() {
set = itemView.findViewById(R.id.set);
weight = itemView.findViewById(R.id.weight);
}
private void setDetailItem(RoutineDetailModel item) {
set.setText(item.getSet().toString() + "set");
}
}
}
RoutineDiffUtil.java
public class RoutineDiffUtil extends DiffUtil.Callback {
private List<Object> oldRoutineList;
private List<Object> newRoutineList;
public RoutineDiffUtil(List<Object> oldRoutineList, List<Object> newRoutineList) {
this.oldRoutineList = oldRoutineList;
this.newRoutineList = newRoutineList;
}
#Override
public int getOldListSize() {
return oldRoutineList.size();
}
#Override
public int getNewListSize() {
return newRoutineList.size();
}
#Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
Object oldObj = oldRoutineList.get(oldItemPosition);
Object newObj = newRoutineList.get(newItemPosition);
if (oldObj instanceof RoutineModel && newObj instanceof RoutineModel) {
return ((RoutineModel) oldObj).id == ((RoutineModel) newObj).id;
}
else if (oldObj instanceof RoutineDetailModel && newObj instanceof RoutineDetailModel) {
return ((RoutineDetailModel) oldObj).id == ((RoutineDetailModel) newObj).id;
}
else if(oldObj instanceof RoutineModel && newObj instanceof RoutineDetailModel) {
return false;
}
else {
return false;
}
}
#Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return (oldRoutineList.get(oldItemPosition)).equals(newRoutineList.get(newItemPosition));
}
}
RoutineDetailModel.java
public class RoutineDetailModel {
public int id;
private int set = 1;
private int weight;
public RoutineDetailModel() {
Random random = new Random();
this.id = random.nextInt();
}
public RoutineDetailModel(int set) {
Random random = new Random();
this.id = random.nextInt();
this.set = set+1;
}
public Integer getSet() {
return set;
}
public int getId() {
return id;
}
#Override
public int hashCode() {
return Objects.hash(set, weight);
}
#Override
public boolean equals(#Nullable Object obj) {
if(obj != null && obj instanceof RoutineDetailModel) {
RoutineDetailModel model = (RoutineDetailModel) obj;
if(this.id == model.getId()) {
return true;
}
}
return false;
}
}
First of all, you should use ListAdapter class with diff util. The problem with your adapter is that, Recycler view recycles views again and again. That is to say that when you entered a text for your first item, this item is used for other views. To solve it after any text change you should keep this text in your model class then you should set this text to the field in onBind() method. To sum up, recycler view uses same view for different items so any data related to any item should be kept in a model and the model should be set to the view in onBind().

Shouldn't DiffUtil compare with hashCode?

I am developing the Workout log app now.
Two items (routine and routine detail) are expressed using one recycler view and adapter.
If i click the Add Routine button, a routine item is added, and the routine basically has one routine detail item.
Routine items have buttons to add or delete routine detail items.
I used DiffUtil to update the item.
In areItemsTheSame(), I used hashCode to compare oldList and newList.
However, there is a problem of unknown cause when adding or deleting items. (Not an error).
If i click the delete button after adding the routine item and the detail item, it works well at first.
The routine detail buttons of the next routine item cannot be added or deleted unless the delete button of the previous routine item is pressed.
If the delete button of the previous routine item is pressed and then the button of the next item is pressed, the addition or deletion is performed.
Why is this?
This happens when you use hashCode comparison.
However, with equals() this does not happen and works fine.
Instead, every time an item is added or deleted, the entire item is updated with blinking.
How did I have to define the DiffUtil class?
CODE
RoutineModel.java
public class RoutineModel {
private ArrayList<RoutineDetailModel> routineDetailList;
private String routine;
public RoutineModel(String routine) {
this.routine = routine;
}
public void addDetail(RoutineDetailModel item) {
if(routineDetailList == null) {
routineDetailList = new ArrayList<>();
}
this.routineDetailList.add(item);
}
public ArrayList<RoutineDetailModel> getDetailItemList() {
return routineDetailList;
}
public int getDetailItemSize() {
return routineDetailList.size();
}
public String getRoutine() {
return routine;
}
public void removeDetails(int index) throws Exception {
this.routineDetailList.remove(index);
}
#Override
public int hashCode() {
return Objects.hash(routineDetailList, routine);
}
#Override
public boolean equals(#Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
RoutineModel that = (RoutineModel) obj;
return Objects.equals(routine, that.routine) && Objects.equals(routineDetailList, that.routineDetailList);
}
}
RoutineAdapter.java
public class RoutineAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
final static int TYPE_ROUTINE = 1;
final static int TYPE_ROUTINE_DETAIL = 2;
private Context context;
private List<Object> mItems = new ArrayList<>();
OnRoutineItemClickListener listener;
public void updateRoutineList(List<Object> newRoutineList) {
final RoutineDiffUtil diffCallback = new RoutineDiffUtil(this.mItems, newRoutineList);
final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);
this.mItems.clear();
this.mItems.addAll(newRoutineList);
diffResult.dispatchUpdatesTo(this);
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
context = parent.getContext();
if (viewType == TYPE_ROUTINE) {
View itemView = LayoutInflater.from(context).inflate(R.layout.routine_item, parent, false);
return new RoutineViewHolder(itemView);
}
View itemView = LayoutInflater.from(context).inflate(R.layout.routine_detail_item, parent, false);
return new RoutineDetailViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
Object object = mItems.get(position);
if(object instanceof RoutineModel) {
setRoutineData((RoutineViewHolder) holder, (RoutineModel) object, position);
}
else if(object instanceof RoutineDetailModel) {
}
}
private void setRoutineData(RoutineViewHolder holder, RoutineModel routineItem, int position){
holder.routine.setText(routineItem.getRoutine());
holder.addSet.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(listener != null) listener.OnAddBtnClick(position);
}
});
holder.deleteSet.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(listener != null) listener.OnDeleteBtnClick(position);
}
});
}
public Object getRoutineItem(int position) {
if(mItems == null || position < 0 || position >= mItems.size())
return null;
return mItems.get(position);
}
#Override
public int getItemCount() {
if(mItems == null)
return -1;
return mItems.size();
}
#Override
public int getItemViewType(int position) {
Object obj = mItems.get(position);
if(obj instanceof RoutineModel) {
return TYPE_ROUTINE;
}
return TYPE_ROUTINE_DETAIL;
}
// detail add,delete click interface
public interface OnRoutineItemClickListener {
public void OnAddBtnClick(int curRoutinePos);
public void OnDeleteBtnClick(int curRoutinePos);
}
public void setOnRoutineClickListener(OnRoutineItemClickListener listener) {
this.listener = listener;
}
public class RoutineViewHolder extends RecyclerView.ViewHolder {
public TextView routine;
public Button addSet;
public Button deleteSet;
public RoutineViewHolder(#NonNull View itemView) {
super(itemView);
routine = itemView.findViewById(R.id.routine);
addSet = itemView.findViewById(R.id.add_set);
deleteSet = itemView.findViewById(R.id.delete_set);
}
}
public class RoutineDetailViewHolder extends RecyclerView.ViewHolder {
public TextView set;
public TextView weight;
public RoutineDetailViewHolder(#NonNull View itemView) {
super(itemView);
set = itemView.findViewById(R.id.set);
weight = itemView.findViewById(R.id.weight);
}
}
}
RoutineDiffUtil.java
public class RoutineDiffUtil extends DiffUtil.Callback {
private List<Object> oldRoutineList;
private List<Object> newRoutineList;
public RoutineDiffUtil(List<Object> oldRoutineList) {
this.oldRoutineList = oldRoutineList;
newRoutineList = new ArrayList<>();
}
public RoutineDiffUtil(List<Object> oldRoutineList, List<Object> newRoutineList) {
this.oldRoutineList = oldRoutineList;
this.newRoutineList = newRoutineList;
}
#Override
public int getOldListSize() {
return oldRoutineList.size();
}
#Override
public int getNewListSize() {
return newRoutineList.size();
}
#Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
// boolean result = oldRoutineList.equals(newRoutineList); // work well
boolean result = oldRoutineList.get(oldItemPosition).hashCode() == newRoutineList.get(newItemPosition).hashCode();
return result;
}
#Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldRoutineList.get(oldItemPosition).equals(newRoutineList.get(newItemPosition));
}
}
MainActivity.java
public class WriteRoutineActivity extends AppCompatActivity {
Button add_routine_btn;
TextView title;
RecyclerView routine_rv;
LinearLayoutManager routineLayoutManger;
RoutineAdapter routineAdapter;
List<RoutineModel> items;
List<String> titleData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_write_routine);
initViews();
setPageTitle(getIntent());
setRoutineRecyclerview();
items = new ArrayList<>();
routineAdapter = new RoutineAdapter();
routine_rv.setAdapter(routineAdapter);
add_routine_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
WorkoutListDialogFragment routineDialog = new WorkoutListDialogFragment();
routineDialog.show(getSupportFragmentManager(), "RoutineListDialog");
}
});
routineAdapter.setOnRoutineClickListener(new RoutineAdapter.OnRoutineItemClickListener() {
#Override
public void OnAddBtnClick(int routinePos) {
Object obj = routineAdapter.getRoutineItem(routinePos);
if(obj instanceof RoutineModel) {
RoutineModel item = (RoutineModel) obj;
item.addDetail(new RoutineDetailModel());
routineAdapter.updateRoutineList(getDataToBeDisplayed());
}
}
#Override
public void OnDeleteBtnClick(int routinePos) {
Object item = routineAdapter.getRoutineItem(routinePos);
if(item instanceof RoutineModel) {
RoutineModel routineModel = (RoutineModel) item;
if(routineModel.getDetailItemSize() > 1) {
try {
routineModel.removeDetails(routineModel.getDetailItemSize() - 1);
} catch (Exception e) {
e.printStackTrace();
}
}
else { // if delete item exists only one
items.remove(routineModel);
}
routineAdapter.updateRoutineList(getDataToBeDisplayed());
}
}
});
}
public void addRoutine(String routine) {
RoutineModel routineModel = new RoutineModel(routine);
RoutineDetailModel routineDetailModel = new RoutineDetailModel();
routineModel.addDetail(routineDetailModel);
items.add(routineModel);
routineAdapter.updateRoutineList(getDataToBeDisplayed());
}
private List<Object> getDataToBeDisplayed() {
List<Object> mixedList = new ArrayList<>();
for(RoutineModel rm: items){
mixedList.add(rm);
if(rm.getDetailItemList() != null && rm.getDetailItemSize() > 0){
for(RoutineDetailModel rmdetilas: rm.getDetailItemList()){
mixedList.add(rmdetilas);
}
}
}
return mixedList;
}
}

Hide the visibility of the nested recyclerview in android on ChildItem Click

I have a nested recycler view on which child item click I want the whole child recycler view to set visibility GONE.
I have tried some way to do it. But keeps on loosing the recycler view state and wrong data show's up. Help, please.
Here is ParentAdapter.java code
public class MessageListAdapter extends RecyclerView.Adapter {
private Context mContext;
private static final int VIEW_TYPE_MESSAGE_SENT = 1;
private static final int VIEW_TYPE_MESSAGE_RECEIVED = 2;
private List<Payload> chatMessageList;
private RecyclerView.RecycledViewPool recycledViewPool;
private OnItemClickListener onItemClickListener;
MessageListAdapter(Context context, List<Payload> chatMessageList, OnItemClickListener onItemClickListener) {
this.mContext = context;
this.chatMessageList = chatMessageList;
this.onItemClickListener = onItemClickListener;
recycledViewPool = new RecyclerView.RecycledViewPool();
}
#Override
public int getItemCount() {
return chatMessageList.size();
}
// Determines the appropriate ViewType according to the sender of the message.
#Override
public int getItemViewType(int position) {
Payload message = chatMessageList.get(position);
if (TextUtils.equals(message.getUserType(), "USER")) {
// If the current user is the sender of the message
return VIEW_TYPE_MESSAGE_SENT;
} else {
// If some other user sent the message
return VIEW_TYPE_MESSAGE_RECEIVED;
}
}
// Inflates the appropriate layout according to the ViewType.
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view;
if (viewType == VIEW_TYPE_MESSAGE_SENT) {
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_user_msg, parent, false);
return new SentMessageHolder(view);
} else {
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_bot_msg, parent, false);
return new ReceivedMessageHolder(view);
}
}
// Passes the message object to a ViewHolder so that the contents can be bound to UI.
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Payload chatMessage = chatMessageList.get(position);
switch (holder.getItemViewType()) {
case VIEW_TYPE_MESSAGE_SENT:
((SentMessageHolder) holder).bind(chatMessage.getMessage(), getFormattedTime());
break;
case VIEW_TYPE_MESSAGE_RECEIVED:
((ReceivedMessageHolder) holder).bind(chatMessage.getMessage(), getFormattedTime());
((ReceivedMessageHolder) holder).bindRv(chatMessage, mContext, recycledViewPool, onItemClickListener);
break;
}
}
private static class SentMessageHolder extends RecyclerView.ViewHolder {
TextView txtViewChatMsgUser;
TextView txtViewDateTimeUser;
SentMessageHolder(View itemView) {
super(itemView);
txtViewChatMsgUser = itemView.findViewById(R.id.txtViewChatMsgUser);
txtViewDateTimeUser = itemView.findViewById(R.id.txtViewDateTimeUser);
}
void bind(String message, String time) {
txtViewChatMsgUser.setText(message);
txtViewDateTimeUser.setText(time);
}
}
private class ReceivedMessageHolder extends RecyclerView.ViewHolder {
TextView txtViewChatMsgBot;
RecyclerView rvDeepLink;
TextView txtViewDateTimeBot;
ReceivedMessageHolder(View itemView) {
super(itemView);
txtViewChatMsgBot = itemView.findViewById(R.id.txtViewChatMsgBot);
rvDeepLink = itemView.findViewById(R.id.itemRvDeepLink);
txtViewDateTimeBot = itemView.findViewById(R.id.txtViewDateTimeBot);
}
void bind(String message, String time) {
txtViewChatMsgBot.setText(message);
txtViewDateTimeBot.setText(time);
}
void bindRv(Payload chatMessage, Context context, RecyclerView.RecycledViewPool recycledViewPool, OnItemClickListener onItemClickListener) {
if (chatMessage.getData() != null && !chatMessage.isOptionSelected()) {
DeepLinkAdapter deepLinkAdapter = new DeepLinkAdapter(context, chatMessage.getData(), onItemClickListener, getAdapterPosition());
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context);
linearLayoutManager.setOrientation(RecyclerView.VERTICAL);
rvDeepLink.setLayoutManager(linearLayoutManager);
rvDeepLink.setAdapter(deepLinkAdapter);
rvDeepLink.setRecycledViewPool(recycledViewPool);
deepLinkAdapter.notifyDataSetChanged();
} else {
rvDeepLink.setVisibility(View.GONE);
}
}
}
private String getFormattedTime() {
SimpleDateFormat dateFormat = new SimpleDateFormat("hh.mm aa", Locale.ENGLISH);
return dateFormat.format(new Date());
}
public void clearData() {
chatMessageList.clear();
notifyDataSetChanged();
}
public void onSelected(int position) {
chatMessageList.get(position).setOptionSelected(true);
notifyItemChanged(position);
}
}
Here is my ChildAdapter.java code:
public class DeepLinkAdapter extends RecyclerView.Adapter<DeepLinkAdapter.DeepLinkViewHolder> {
private List<DataItem> dataItemList;
private Context context;
private OnItemClickListener onItemClickListener;
private int parentPos;
DeepLinkAdapter(Context context, List<DataItem> dataItemList, OnItemClickListener onItemClickListener, int parentPos) {
this.context = context;
this.dataItemList = dataItemList;
this.onItemClickListener = onItemClickListener;
this.parentPos = parentPos;
}
#NonNull
#Override
public DeepLinkViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new DeepLinkViewHolder(LayoutInflater.from(context).inflate(R.layout.inner_bot_msg, parent, false), onItemClickListener, parentPos);
}
#Override
public void onBindViewHolder(#NonNull final DeepLinkViewHolder holder, final int position) {
DataItem dataItem = dataItemList.get(position);
if (TextUtils.isEmpty(dataItem.getDeeplink())) {
holder.deepLinkText.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
} else {
holder.deepLinkText.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_right_arrow, 0);
}
if (!TextUtils.isEmpty(dataItem.getText())) {
holder.deepLinkText.setVisibility(View.VISIBLE);
holder.deepLinkText.setText(dataItem.getText());
} else {
holder.deepLinkText.setVisibility(View.GONE);
}
}
#Override
public int getItemCount() {
if (dataItemList != null) {
return dataItemList.size();
} else {
return 0;
}
}
class DeepLinkViewHolder extends RecyclerView.ViewHolder {
private TextView deepLinkText;
DeepLinkViewHolder(View itemView, OnItemClickListener onItemClickListener, int parentPos) {
super(itemView);
deepLinkText = itemView.findViewById(R.id.innerDeepLinkMsgText);
if (onItemClickListener != null) {
deepLinkText.setOnClickListener(v -> {
onItemClickListener.onItemClick(getAdapterPosition(), parentPos);
});
}
}
}
}
Here is my Click Listener Code in the Activity:
#Override
public void onItemClick(int childPos, int parentPos) {
if (TextUtils.isEmpty(chatMessageList.get(parentPos).getData().get(childPos).getDeeplink())) {
String message = chatMessageList.get(parentPos).getData().get(childPos).getText();
if (!viewModel.sendMessage(message)) {
setMessage(getString(R.string.error_something_went_wrong), ChatBotManager.UserType.BOT.toString());
} else {
messageListAdapter.onSelected(parentPos);
setMessage(message, ChatBotManager.UserType.USER.toString());
}
} else {
if (TextUtils.equals(chatMessageList.get(parentPos).getData().get(childPos).getDeeplink(), "restart")) {
if (messageListAdapter != null) {
messageListAdapter.clearData();
viewModel.sendMessage("start");
}
} else {
String uri = chatMessageList.get(parentPos).getData().get(childPos).getDeeplink();
Intent newIntent = new Intent(ApplicationClass.getContext(), TalkLinkingActivity.class);
newIntent.setData(Uri.parse(uri));
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newIntent);
finish();
}
}
}
Please help what I am missing here, My goal is to have a click listener from the child adapter on Activity, and also after the click on the item, I want to remove the whole recycler view. Just like a chatbot in Swiggy.
Have a method in DeepLinkAdapter that clears the whole list:
public class DeepLinkAdapter extends RecyclerView.Adapter<DeepLinkAdapter.DeepLinkViewHolder> {
.......
public void clearTheWholeList(){
dataItemList.clear();
notifyDataSetChanged();
}
}
Have a method in your MessageListAdapter that removes an item completely:
public class MessageListAdapter extends RecyclerView.Adapter {
......
......
private int positionToClear = -1;
public void removeItem(int position){
positionToClear = position;
notifyDataSetChanged();
}
//in onBindViewHolder
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
............
............
//pass the positionToClear here
((ReceivedMessageHolder) holder).bindRv(chatMessage, mContext, recycledViewPool, onItemClickListener , positionToClear);
}
.......
}
In ReceivedMessageHolder
private class ReceivedMessageHolder extends RecyclerView.ViewHolder {
//here add new param for removed position
void bindRv(Payload chatMessage, Context context, RecyclerView.RecycledViewPool recycledViewPool, OnItemClickListener onItemClickListener, int positionToClear) {
if (chatMessage.getData() != null && !chatMessage.isOptionSelected()) {
DeepLinkAdapter deepLinkAdapter = new DeepLinkAdapter(context, chatMessage.getData(), onItemClickListener, getAdapterPosition());
//do a check here
if(getAdapterPosition() == positionToClear){
deepLinkAdapter.clearTheWholeList();
}
.......
.......
.......
} else {
rvDeepLink.setVisibility(View.GONE);
}
}
}
Assuming the onItemClick interface is working:
#Override
public void onItemClick(int childPos, int parentPos) {
...........
...........
//somewhere where you want the item to be removed
messageListAdapter.removeItem(parentPos);
............
............
}

How to efficiently loading native ads on demand with the recyclerview adapter?

What i am doing is, that i have a recyclerView which has it's adapter and from within adapter i am loading the nativeAds. But due to loading the ads within the recyclerView instead of preloading the ads my recyclerView is not scrolling smoothly.
And also i tried to load the native ad on different thread but that also was't helpful.
Any ideas how to load the native ad without sacrificing the performance??
public class GetInspiredAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static int VIEW_TYPE_ADS = 0;
public static int VIEW_TYPE_NOTADS = 1;
// this shows that the ad is to be added after this many items.
public static int ADS_AFTER_HOW_MANY_ITEMS = 3;
private boolean isNetworkAvailable = false;
private Context context;
private ArrayList<Object> list;
private GetInspiredListener listener;
public GetInspiredAdapter(Context context, ArrayList<Object> list, GetInspiredListener listener) {
this.context = context;
this.list = list;
this.listener = listener;
}
private void addNativeToList() {
int i = ADS_AFTER_HOW_MANY_ITEMS;
while (i < list.size()) {
list.add(i, new UnifiedNativeAdView(context));
i += ADS_AFTER_HOW_MANY_ITEMS + 1;
}
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int viewType) {
if (viewType == VIEW_TYPE_ADS) {
View unifiedNativeLayoutView = LayoutInflater.from(context).inflate(R.layout.ad_unified, viewGroup, false);
unifiedNativeLayoutView.setTag(new Integer(GetInspiredAdapter.VIEW_TYPE_ADS));
return new UnifiedNativeAdViewHolder(unifiedNativeLayoutView);
} else {
View itemView = LayoutInflater.from(context).inflate(R.layout.image_item, viewGroup, false);
itemView.setTag(new Integer(GetInspiredAdapter.VIEW_TYPE_NOTADS));
return new GetInspiredViewHolder(itemView);
}
}
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
if (viewType == VIEW_TYPE_ADS) {
if (!isNetworkAvailable) {
list.remove(position);
notifyDataSetChanged();
return;
}
AdLoader.Builder builder = new AdLoader.Builder(context, Constants.INSPIRED_MOB)
.forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
populateNativeAdView(unifiedNativeAd, (UnifiedNativeAdViewHolder) holder);
}
}).withAdListener(new AdListener() {
#Override
public void onAdFailedToLoad(int i) {
super.onAdFailedToLoad(i);
}
});
builder.build().loadAd(new AdRequest.Builder().build());
} else if (viewType == VIEW_TYPE_NOTADS) {
LoadImage((InspiredObject) list.get(getItemIndex(position)), (GetInspiredViewHolder) holder);
}
}
private void LoadImage(InspiredObject obj, GetInspiredViewHolder viewHolder) {
//Url link to images
String url = "http://aim-itech.com/mandala/image/";
String string = url + obj.low;
Glide.with(context).load(string).override(Constants.SAMPLE_SIZE_MEDIUM).into(viewHolder.imageView);
Log.e("TAG", string);
}
private void populateNativeAdView(UnifiedNativeAd nativeAd, UnifiedNativeAdViewHolder holder) {
if (nativeAd == null) {
holder.getAdView().setVisibility(View.INVISIBLE);
holder.textLoading.setVisibility(View.VISIBLE);
return;
}
holder.textLoading.setVisibility(View.GONE);
UnifiedNativeAdView adView = holder.getAdView();
adView.setVisibility(View.VISIBLE);
((TextView) adView.getHeadlineView()).setText(nativeAd.getHeadline());
((TextView) adView.getBodyView()).setText(nativeAd.getBody());
((Button) adView.getCallToActionView()).setText(nativeAd.getCallToAction());
NativeAd.Image icon = nativeAd.getIcon();
if (icon == null) {
adView.getIconView().setVisibility(View.INVISIBLE);
} else {
((ImageView) adView.getIconView()).setImageDrawable(icon.getDrawable());
adView.getIconView().setVisibility(View.VISIBLE);
}
if (nativeAd.getPrice() == null) {
adView.getPriceView().setVisibility(View.INVISIBLE);
} else {
adView.getPriceView().setVisibility(View.VISIBLE);
((TextView) adView.getPriceView()).setText(nativeAd.getPrice());
}
if (nativeAd.getStore() == null) {
adView.getStoreView().setVisibility(View.INVISIBLE);
} else {
adView.getStoreView().setVisibility(View.VISIBLE);
((TextView) adView.getStoreView()).setText(nativeAd.getStore());
}
if (nativeAd.getStarRating() == null) {
adView.getStarRatingView().setVisibility(View.INVISIBLE);
} else {
((RatingBar) adView.getStarRatingView())
.setRating(nativeAd.getStarRating().floatValue());
adView.getStarRatingView().setVisibility(View.VISIBLE);
}
if (nativeAd.getAdvertiser() == null) {
adView.getAdvertiserView().setVisibility(View.INVISIBLE);
} else {
((TextView) adView.getAdvertiserView()).setText(nativeAd.getAdvertiser());
adView.getAdvertiserView().setVisibility(View.VISIBLE);
}
// Assign native ad object to the native view.
adView.setNativeAd(nativeAd);
}
public int getItemIndex(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
Object recyclerViewItem = list.get(getItemIndex(position));
if (recyclerViewItem instanceof UnifiedNativeAd) {
return VIEW_TYPE_ADS;
} else if (recyclerViewItem instanceof UnifiedNativeAdView) {
return VIEW_TYPE_ADS;
}
return VIEW_TYPE_NOTADS;
}
public boolean isNetworkAvailable() {
return isNetworkAvailable;
}
public void setNetworkAvailable(boolean networkAvailable) {
isNetworkAvailable = networkAvailable;
if (isNetworkAvailable) {
addNativeToList();
}
}
#Override
public int getItemCount() {
return list.size();
}
public class GetInspiredViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
public GetInspiredViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imageProf);
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
InspiredObject inspiredObject = (InspiredObject) list.get(getAdapterPosition());
Intent i = new Intent(context, InspiredActivity.class);
i.putExtra("image", inspiredObject.high);
listener.onClick(i);
}
});
}
}
public class UnifiedNativeAdViewHolder extends RecyclerView.ViewHolder {
private UnifiedNativeAdView adView;
private TextView textLoading;
private CardView adContainer;
public UnifiedNativeAdView getAdView() {
return adView;
}
UnifiedNativeAdViewHolder(View view) {
super(view);
textLoading = view.findViewById(R.id.native_loading_text);
adView = view.findViewById(R.id.native_ad_view);
adContainer = view.findViewById(R.id.ad_unified_conatiner);
// The MediaView will display a video asset if one is present in the ad, and the
// first image asset otherwise.
adView.setMediaView((MediaView) adView.findViewById(R.id.ad_media));
// Register the view used for each individual asset.
adView.setHeadlineView(adView.findViewById(R.id.ad_headline));
adView.setBodyView(adView.findViewById(R.id.ad_body));
adView.setCallToActionView(adView.findViewById(R.id.ad_call_to_action));
adView.setIconView(adView.findViewById(R.id.ad_icon));
adView.setPriceView(adView.findViewById(R.id.ad_price));
adView.setStarRatingView(adView.findViewById(R.id.ad_stars));
adView.setStoreView(adView.findViewById(R.id.ad_store));
adView.setAdvertiserView(adView.findViewById(R.id.ad_advertiser));
}
}
}
surprised there is no answer here.
The approach I would use outside of the recyclerview adapter:
adLoader.loadAds(new AdRequest.Builder().build(), NUMBER_OF_ADS_TO_LOAD(Max 5 according to docs);
instead usual adLoader.loadAd
and then
builder.forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
// OnUnifiedNativeAdLoadedListener implementation.
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
nativeAds.add(unifiedNativeAd);
}
});
where
private List<UnifiedNativeAd> nativeAds = new ArrayList<>();
which you pass to your recyclerview adapter and mix in your other items.
This will need some memory handling with destroy called before you request another list etc. but the idea is to preload a list of ads instead of loading them while scrolling

RecyclerView in RecyclerView parent.notifyDataSetChanged loose position of child RecyclerView

I develop a fragment using Horizontal RecyclerView in a Vertical RecyclerView (like Google Play Store).
When i notifyDataSetChanged from the parent RecyclerView, the child RecyclerView lose the position because the setAdapter is call in the onBindViewHolder I think. Also when i scroll to the 5th position in the first horizontal recyclerview if i scroll down and come back up i loose the 5th position.
I try to use RecyclerView.scrollToPosition() but that don't work.
So i think i have two solution :
a way (by a method or setting) to keep the position of my child recycler view. (BEST SOLUTION)
a way to set manually the recyclerview position to where it was before the refresh. (ELSE SOLUTION)
Here my Parent Adapter :
public class ProfilesCardViewListAdapter extends RecyclerView.Adapter<ProfilesCardViewListAdapter.ItemRowHolder> {
private ArrayList<AidodysProfile> sectionsList;
private Context context;
private boolean[] isShown;
private ProfileCardViewItemAdapter itemAdapters[];
public ProfilesCardViewListAdapter(ArrayList<AidodysProfile> sectionsList, Context context) {
this.sectionsList = sectionsList;
this.context = context;
this.isShown = new boolean[sectionsList.size()];
this.itemAdapters = new ProfileCardViewItemAdapter[sectionsList.size()];
for (int i = 0; i < sectionsList.size(); i++) {
this.isShown[i] = true;
this.itemAdapters[i] = new ProfileCardViewItemAdapter(sectionsList.get(i).getProfiles(), context, this);
}
}
#Override
public ItemRowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_card_view_horizontal, null);
final ItemRowHolder rowHolder = new ItemRowHolder(view);
return rowHolder;
}
#Override
public void onBindViewHolder(final ItemRowHolder holder, final int position) {
String sectionName = sectionsList.get(position).getName();
AidodysProfile[] sectionItems = sectionsList.get(position).getProfiles();
holder.sectionTitle.setTextSize(context.getResources().getDimension(R.dimen.text_size_profileslist_section_title));
holder.sectionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showHideSection(holder, position);
}
});
if (isShown[position]) {
holder.itemRecyclerView.setVisibility(View.VISIBLE);
holder.sectionButton.setText(context.getString(R.string.action_profiles_section_hide));
} else {
holder.itemRecyclerView.setVisibility(View.GONE);
holder.sectionButton.setText(context.getText(R.string.action_profiles_section_show));
}
if (!sectionsList.get(position).isLeaf()) { // FOLDER
if (sectionName.equals("")) {
holder.sectionTitle.setVisibility(View.GONE);
holder.sectionButton.setVisibility(View.GONE);
} else {
holder.sectionTitle.setVisibility(View.VISIBLE);
holder.sectionButton.setVisibility(View.VISIBLE);
}
holder.sectionTitle.setText(sectionName);
} else { // PROFILE
return;
}
holder.itemRecyclerView.setHasFixedSize(true);
holder.itemRecyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
holder.itemRecyclerView.setAdapter(itemAdapters[position]);
}
private void showHideSection(ItemRowHolder holder, int position) {
if (holder.itemRecyclerView.getVisibility() == View.VISIBLE) {
isShown[position] = false;
holder.itemRecyclerView.setVisibility(View.GONE);
holder.sectionButton.setText(context.getText(R.string.action_profiles_section_show));
} else {
isShown[position] = true;
holder.itemRecyclerView.setVisibility(View.VISIBLE);
holder.sectionButton.setText(context.getString(R.string.action_profiles_section_hide));
}
}
#Override
public int getItemCount() {
return (sectionsList != null ? sectionsList.size() : 0);
}
public class ItemRowHolder extends RecyclerView.ViewHolder {
protected TextView sectionTitle;
protected RecyclerView itemRecyclerView;
protected Button sectionButton;
public ItemRowHolder(View view) {
super(view);
this.sectionTitle = (TextView) view.findViewById(R.id.section_title);
this.itemRecyclerView = (RecyclerView) view.findViewById(R.id.item_recycler_view);
this.sectionButton = (Button) view.findViewById(R.id.section_button);
}
}
}
Child Adapter :
class ProfileCardViewItemAdapter extends RecyclerView.Adapter<ProfileCardViewItemAdapter.SingleItemRowHolder> {
private AidodysProfile[] itemsList;
private CurrentUser currentUser;
private Context context;
private int selectedPos = -1;
private ProfilesCardViewListAdapter parent;
public ProfileCardViewItemAdapter(AidodysProfile[] itemsList, Context context, ProfilesCardViewListAdapter parent) {
this.itemsList = itemsList;
this.context = context;
this.parent = parent;
this.currentUser = CurrentUser.getInstance(context);
}
#Override
public SingleItemRowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_card_view_horizontal, null);
SingleItemRowHolder rowHolder = new SingleItemRowHolder(view);
return (rowHolder);
}
#Override
public void onBindViewHolder(final SingleItemRowHolder holder, final int position) {
AidodysProfile profile = itemsList[position];
holder.itemCardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
selectProfile(holder, position);
}
});
if (profile.equals(currentUser.getProfile())) {
selectedPos = position;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
holder.itemCardView.setCardBackgroundColor(context.getColor(R.color.aidodysRed));
} else {
holder.itemCardView.setCardBackgroundColor(context.getResources().getColor(R.color.aidodysRed));
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
holder.itemCardView.setCardBackgroundColor(context.getColor(R.color.white));
} else {
holder.itemCardView.setCardBackgroundColor(context.getResources().getColor(R.color.white));
}
}
holder.itemTitle.setText(profile.getName());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
holder.itemPicture.setImageDrawable(context.getDrawable(R.drawable.ic_sheet_smile_black_48dp));
holder.button1.setImageDrawable(context.getDrawable(R.drawable.ic_edit_black_24dp));
holder.button2.setImageDrawable(context.getDrawable(R.drawable.ic_look_profile));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
holder.itemTitle.setTextAppearance(R.style.Aidodys_Text_ProfilesList_Item);
holder.itemPicture.setColorFilter(context.getColor(R.color.white));
holder.topParts.setBackgroundColor(context.getColor(R.color.aidodysRed));
} else {
holder.itemTitle.setTextColor(context.getResources().getColor(R.color.white));
holder.itemTitle.setTextSize(context.getResources().getDimension(R.dimen.text_size_profileslist_item));
holder.itemPicture.setColorFilter(context.getResources().getColor(R.color.white));
holder.topParts.setBackgroundColor(context.getResources().getColor(R.color.aidodysRed));
}
} else {
holder.button1.setImageDrawable(context.getResources().getDrawable(R.drawable.ic_edit_black_24dp));
holder.button2.setImageDrawable(context.getResources().getDrawable(R.drawable.ic_look_profile));
holder.itemTitle.setTextColor(context.getResources().getColor(R.color.white));
holder.itemTitle.setTextSize(context.getResources().getDimension(R.dimen.text_size_profileslist_item));
holder.itemPicture.setImageDrawable(context.getResources().getDrawable(R.drawable.ic_sheet_smile_black_48dp));
holder.itemPicture.setColorFilter(context.getResources().getColor(R.color.white));
holder.topParts.setBackgroundColor(context.getResources().getColor(R.color.aidodysRed));
}
}
private void selectProfile(SingleItemRowHolder holder, int position) {
SharedPreferences.Editor editor = context.getSharedPreferences("Aidodys", 0).edit();
editor.putString("profile", new Gson().toJson(itemsList[position]));
editor.apply();
currentUser.setProfile(itemsList[position]);
parent.notifyDataSetChanged();
notifyDataSetChanged();
((RecyclerView)holder.itemCardView.getParent()).scrollToPosition(position);
selectedPos = position;
}
#Override
public int getItemCount() {
return (itemsList != null ? itemsList.length : 0);
}
public class SingleItemRowHolder extends RecyclerView.ViewHolder {
protected TextView itemTitle;
protected ImageView itemPicture;
protected CardView itemCardView;
protected ImageView button1;
protected ImageView button2;
protected LinearLayout topParts;
public SingleItemRowHolder(View view) {
super(view);
this.itemTitle = (TextView)view.findViewById(R.id.item_title);
this.itemPicture = (ImageView)view.findViewById(R.id.item_picture);
this.itemCardView = (CardView)view.findViewById(R.id.card_view_list_item);
this.topParts = (LinearLayout)view.findViewById(R.id.card_view_list_item_top_part);
this.button1 = (ImageView)view.findViewById(R.id.item_button_1);
this.button2 = (ImageView)view.findViewById(R.id.item_button_2);
}
}
}
If someone has a solution for me
Thank you
Store x scroll offset in a SparseArray for position and restore when bind view holder.
public class ProfilesCardViewListAdapter extends RecyclerView.Adapter<ProfilesCardViewListAdapter.ItemRowHolder> {
private SparseIntArray sparseArray = new SparseIntArray();
#Override
public void onBindViewHolder(final ItemRowHolder holder, final int position) {
// Use srollBy for animate scrolling
holder.itemRecyclerView.srollBy(sparseArray.get(position, 0), 0);
// Or scrollTo for restore previous x offset
//holder.itemRecyclerView.srollTo(sparseArray.get(position, 0), 0);
holder.itemRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
sparseArray.put(position, dx);
}
}
}
}
I found a solution, i use the onTouchListener in the child recyclerView to set a scrollPosition (i don't use onScrollListener because this method is deprecated) i implement a getter to this field to get the scroll position from the parent RecyclerView and so at the end of the onBindViewHolder in the parent RecyclerView i call (child)RecyclerView.scrollToPosition(scrollPosition).
And that's make the job
Parent RecyclerViewAdapter :
public class ProfilesCardViewListAdapter extends RecyclerView.Adapter<ProfilesCardViewListAdapter.ItemRowHolder> {
private ArrayList<AidodysProfile> sectionsList;
private Context context;
private boolean[] isShown;
private ProfileCardViewItemAdapter itemAdapters[];
public ProfilesCardViewListAdapter(ArrayList<AidodysProfile> sectionsList, Context context) {
this.sectionsList = sectionsList;
this.context = context;
this.isShown = new boolean[sectionsList.size()];
this.itemAdapters = new ProfileCardViewItemAdapter[sectionsList.size()];
for (int i = 0; i < sectionsList.size(); i++) {
this.isShown[i] = true;
this.itemAdapters[i] = new ProfileCardViewItemAdapter(sectionsList.get(i).getProfiles(), context, this);
}
}
#Override
public ItemRowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_card_view_horizontal, null);
final ItemRowHolder rowHolder = new ItemRowHolder(view);
rowHolder.itemRecyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
return rowHolder;
}
#Override
public void onBindViewHolder(final ItemRowHolder holder, final int position) {
String sectionName = sectionsList.get(position).getName();
AidodysProfile[] sectionItems = sectionsList.get(position).getProfiles();
holder.sectionTitle.setTextSize(context.getResources().getDimension(R.dimen.text_size_profileslist_section_title));
holder.sectionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showHideSection(holder, position);
}
});
if (isShown[position]) {
holder.itemRecyclerView.setVisibility(View.VISIBLE);
holder.sectionButton.setText(context.getString(R.string.action_profiles_section_hide));
} else {
holder.itemRecyclerView.setVisibility(View.GONE);
holder.sectionButton.setText(context.getText(R.string.action_profiles_section_show));
}
if (!sectionsList.get(position).isLeaf()) { // FOLDER
if (sectionName.equals("")) {
holder.sectionTitle.setVisibility(View.GONE);
holder.sectionButton.setVisibility(View.GONE);
} else {
holder.sectionTitle.setVisibility(View.VISIBLE);
holder.sectionButton.setVisibility(View.VISIBLE);
}
holder.sectionTitle.setText(sectionName);
} else { // PROFILE
return;
}
holder.itemRecyclerView.setHasFixedSize(true);
holder.itemRecyclerView.setAdapter(itemAdapters[position]);
holder.itemRecyclerView.scrollToPosition(itemAdapters[position].getScrollPos());
}
private void showHideSection(ItemRowHolder holder, int position) {
if (holder.itemRecyclerView.getVisibility() == View.VISIBLE) {
isShown[position] = false;
holder.itemRecyclerView.setVisibility(View.GONE);
holder.sectionButton.setText(context.getText(R.string.action_profiles_section_show));
} else {
isShown[position] = true;
holder.itemRecyclerView.setVisibility(View.VISIBLE);
holder.sectionButton.setText(context.getString(R.string.action_profiles_section_hide));
}
}
#Override
public int getItemCount() {
return (sectionsList != null ? sectionsList.size() : 0);
}
public class ItemRowHolder extends RecyclerView.ViewHolder {
protected TextView sectionTitle;
protected RecyclerView itemRecyclerView;
protected Button sectionButton;
public ItemRowHolder(View view) {
super(view);
this.sectionTitle = (TextView) view.findViewById(R.id.section_title);
this.itemRecyclerView = (RecyclerView) view.findViewById(R.id.item_recycler_view);
this.sectionButton = (Button) view.findViewById(R.id.section_button);
}
}
}
Child RecyclerViewAdapter :
class ProfileCardViewItemAdapter extends RecyclerView.Adapter<ProfileCardViewItemAdapter.SingleItemRowHolder> {
private AidodysProfile[] itemsList;
private CurrentUser currentUser;
private Context context;
private int scrollPos = 0;
private ProfilesCardViewListAdapter parent;
public int getScrollPos() {
return scrollPos;
}
public ProfileCardViewItemAdapter(AidodysProfile[] itemsList, Context context, ProfilesCardViewListAdapter parent) {
this.itemsList = itemsList;
this.context = context;
this.parent = parent;
this.currentUser = CurrentUser.getInstance(context);
}
#Override
public SingleItemRowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_card_view_horizontal, null);
SingleItemRowHolder rowHolder = new SingleItemRowHolder(view);
return (rowHolder);
}
#Override
public void onBindViewHolder(final SingleItemRowHolder holder, final int position) {
AidodysProfile profile = itemsList[position];
holder.itemCardView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
scrollPos = position;
return false;
}
});
holder.itemCardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
selectProfile(holder, position);
}
});
if (profile.getId() == currentUser.getProfile().getId()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
holder.itemCardView.setCardBackgroundColor(context.getColor(R.color.aidodysRed));
} else {
holder.itemCardView.setCardBackgroundColor(context.getResources().getColor(R.color.aidodysRed));
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
holder.itemCardView.setCardBackgroundColor(context.getColor(R.color.white));
} else {
holder.itemCardView.setCardBackgroundColor(context.getResources().getColor(R.color.white));
}
}
holder.itemTitle.setText(profile.getName());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
holder.itemPicture.setImageDrawable(context.getDrawable(R.drawable.ic_sheet_smile_black_48dp));
holder.button1.setImageDrawable(context.getDrawable(R.drawable.ic_edit_black_24dp));
holder.button2.setImageDrawable(context.getDrawable(R.drawable.ic_look_profile));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
holder.itemTitle.setTextAppearance(R.style.Aidodys_Text_ProfilesList_Item);
holder.itemPicture.setColorFilter(context.getColor(R.color.white));
holder.topParts.setBackgroundColor(context.getColor(R.color.aidodysRed));
} else {
holder.itemTitle.setTextColor(context.getResources().getColor(R.color.white));
holder.itemTitle.setTextSize(context.getResources().getDimension(R.dimen.text_size_profileslist_item));
holder.itemPicture.setColorFilter(context.getResources().getColor(R.color.white));
holder.topParts.setBackgroundColor(context.getResources().getColor(R.color.aidodysRed));
}
} else {
holder.button1.setImageDrawable(context.getResources().getDrawable(R.drawable.ic_edit_black_24dp));
holder.button2.setImageDrawable(context.getResources().getDrawable(R.drawable.ic_look_profile));
holder.itemTitle.setTextColor(context.getResources().getColor(R.color.white));
holder.itemTitle.setTextSize(context.getResources().getDimension(R.dimen.text_size_profileslist_item));
holder.itemPicture.setImageDrawable(context.getResources().getDrawable(R.drawable.ic_sheet_smile_black_48dp));
holder.itemPicture.setColorFilter(context.getResources().getColor(R.color.white));
holder.topParts.setBackgroundColor(context.getResources().getColor(R.color.aidodysRed));
}
}
private void selectProfile(SingleItemRowHolder holder, int position) {
SharedPreferences.Editor editor = context.getSharedPreferences("Aidodys", 0).edit();
editor.putString("profile", new Gson().toJson(itemsList[position]));
editor.apply();
currentUser.setProfile(itemsList[position]);
parent.notifyDataSetChanged();
}
#Override
public int getItemCount() {
return (itemsList != null ? itemsList.length : 0);
}
public class SingleItemRowHolder extends RecyclerView.ViewHolder {
protected TextView itemTitle;
protected ImageView itemPicture;
protected CardView itemCardView;
protected ImageView button1;
protected ImageView button2;
protected LinearLayout topParts;
public SingleItemRowHolder(View view) {
super(view);
this.itemTitle = (TextView)view.findViewById(R.id.item_title);
this.itemPicture = (ImageView)view.findViewById(R.id.item_picture);
this.itemCardView = (CardView)view.findViewById(R.id.card_view_list_item);
this.topParts = (LinearLayout)view.findViewById(R.id.card_view_list_item_top_part);
this.button1 = (ImageView)view.findViewById(R.id.item_button_1);
this.button2 = (ImageView)view.findViewById(R.id.item_button_2);
}
}
}

Categories

Resources