I am trying to figure out how exactly Heterogeneous Recyclerview works and adjust it to my needs. I have 3 layouts
in it. The first one is header with a BottomBar
(which in this case is not at the bottom), and it is always shown. The other 2 layouts
are switched depending on which tab in the BottomBar
is clicked. The first tab in the BottomBar
will show the grid layout
, the second tab should show the list layout
. I've managed to implement it but there is a slight flicked and changing of the lists is not really smooth. Also when clicking the 2nd tab, the first one is still selected. On second click of the 2nd tab, then it is selected. How can I make it smoother and also make the particular tab selected on first click?
Adapter
public class ProfileAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final int HEADER_TYPE = 0;
private final int IMAGE_GRID_TYPE = 1;
private final int IMAGE_LIST_TYPE = 2;
private final int cellSize;
private Context mContext;
private List<Home> mHomeList;
private boolean onBind;
private OnHeaderItemClickedListener mListener;
int selectedPosition;
public ProfileAdapter(Context context, List<Home> homeList) {
this.mContext = context;
this.mHomeList = homeList;
this.cellSize = Utils.getScreenWidth(context) / 3;
}
public interface OnHeaderItemClickedListener {
void onTabGridClicked();
void onTabListClicked();
}
@Override
public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
super.onDetachedFromRecyclerView(recyclerView);
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mContext);
switch (viewType) {
case HEADER_TYPE:
View viewHeader = inflater.inflate(R.layout.item_profile_header, parent, false);
StaggeredGridLayoutManager.LayoutParams lp1 = (StaggeredGridLayoutManager.LayoutParams) viewHeader.getLayoutParams();
lp1.setFullSpan(true);
viewHeader.setLayoutParams(lp1);
return new ProfileAdapter.HeaderHolder(viewHeader);
case IMAGE_GRID_TYPE:
View viewGridImage = inflater.inflate(R.layout.item_profile_grid_image, parent, false);
StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) viewGridImage.getLayoutParams();
layoutParams.height = cellSize;
layoutParams.width = cellSize;
layoutParams.setFullSpan(false);
viewGridImage.setLayoutParams(layoutParams);
return new ImageGridHolder(viewGridImage);
case IMAGE_LIST_TYPE:
View viewListImage = inflater.inflate(R.layout.item_profile_list_image, parent, false);
StaggeredGridLayoutManager.LayoutParams lp3 = (StaggeredGridLayoutManager.LayoutParams) viewListImage.getLayoutParams();
lp3.setFullSpan(true);
viewListImage.setLayoutParams(lp3);
return new ImageListHolder(viewListImage);
}
return null;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case HEADER_TYPE:
onBind = true;
bindHeader((HeaderHolder) holder, mHomeList.get(position));
onBind = false;
break;
case IMAGE_GRID_TYPE:
onBind = true;
bindGridImage((ImageGridHolder) holder, mHomeList.get(position));
onBind = false;
break;
case IMAGE_LIST_TYPE:
onBind = true;
bindListImage((ImageListHolder) holder, mHomeList.get(position));
onBind = false;
break;
}
}
private void bindHeader(final HeaderHolder holder, Home home) {
holder.getItemProfileHeaderBinding().setHome(home);
holder.getItemProfileHeaderBinding().bottomBar.setOnTabSelectListener(new OnTabSelectListener() {
@Override
public void onTabSelected(@IdRes int tabId) {
switch (tabId) {
case R.id.tab_grid:
if (!onBind) {
mListener.onTabGridClicked();
selectedPosition = holder.getLayoutPosition();
notifyItemChanged(selectedPosition);
}
break;
case R.id.tab_list:
if (!onBind) {
mListener.onTabListClicked();
selectedPosition = holder.getLayoutPosition();
notifyItemChanged(selectedPosition);
}
break;
}
}
});
adjustTabs(holder);
}
private void bindGridImage(ImageGridHolder holder, Home home) {
holder.getItemProfileGridImageBinding().setHome(home);
Uri uri = new Uri.Builder()
.scheme(UriUtil.LOCAL_RESOURCE_SCHEME)
.path(String.valueOf(R.drawable.ap_android_icon))
.build();
holder.getItemProfileGridImageBinding().ivImage.setImageURI(uri);
}
private void bindListImage(ImageListHolder holder, Home home) {
holder.getItemProfileListImageBinding().setHome(home);
}
@Override
public int getItemViewType(int position) {
if (isPositionHeader(position)) {
return HEADER_TYPE;
}
if (mHomeList.get(position).getGridListType() == 2) {
return IMAGE_LIST_TYPE;
} else {
return IMAGE_GRID_TYPE;
}
}
private boolean isPositionHeader(int position) {
return position == 0;
}
@Override
public int getItemCount() {
return mHomeList.size();
}
private void adjustTabs(HeaderHolder holder) {
holder.getItemProfileHeaderBinding().bottomBar.getTabWithId(R.id.tab_grid).setPadding(0, 30, 0, 0);
holder.getItemProfileHeaderBinding().bottomBar.getTabWithId(R.id.tab_list).setPadding(0, 30, 0, 0);
holder.getItemProfileHeaderBinding().bottomBar.getTabWithId(R.id.tab_group).setPadding(0, 30, 0, 0);
holder.getItemProfileHeaderBinding().bottomBar.getTabWithId(R.id.tab_bookmark).setPadding(0, 30, 0, 0);
}
private static class HeaderHolder extends RecyclerView.ViewHolder {
ItemProfileHeaderBinding mItemProfileHeaderBinding;
HeaderHolder(View itemView) {
super(itemView);
mItemProfileHeaderBinding = DataBindingUtil.bind(itemView);
}
ItemProfileHeaderBinding getItemProfileHeaderBinding() {
return mItemProfileHeaderBinding;
}
}
private static class ImageGridHolder extends RecyclerView.ViewHolder {
ItemProfileGridImageBinding mItemProfileGridImageBinding;
ImageGridHolder(View itemView) {
super(itemView);
mItemProfileGridImageBinding = DataBindingUtil.bind(itemView);
}
ItemProfileGridImageBinding getItemProfileGridImageBinding() {
return mItemProfileGridImageBinding;
}
}
private static class ImageListHolder extends RecyclerView.ViewHolder {
ItemProfileListImageBinding mItemProfileListImageBinding;
ImageListHolder(View itemView) {
super(itemView);
mItemProfileListImageBinding = DataBindingUtil.bind(itemView);
}
ItemProfileListImageBinding getItemProfileListImageBinding() {
return mItemProfileListImageBinding;
}
}
public void addOnHeaderItemClickListener(OnHeaderItemClickedListener listener) {
this.mListener = listener;
}
}
Fragment
where the tab clicking happens
public class ProfileFragment extends BaseFragment implements ProfileAdapter.OnHeaderItemClickedListener {
private static final String ARG_PARAM1 = "param1";
FragmentProfileMultipleBinding mBinder;
FragmentManager mFragmentManager;
Home mHome;
ProfileAdapter mAdapter;
List<Home> mHomeList;
StaggeredGridLayoutManager mManager;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mBinder = DataBindingUtil.inflate(inflater, R.layout.fragment_profile_multiple, container, false);
mFragmentManager = getChildFragmentManager();
mHome = new Home();
populateList();
mManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
mAdapter = new ProfileAdapter(getContext(), mHomeList);
mBinder.rvGrid.setLayoutManager(mManager);
mBinder.rvGrid.setAdapter(mAdapter);
mAdapter.addOnHeaderItemClickListener(this);
setUIListeners();
return mBinder.getRoot();
}
private void populateList() {
for (int i = 0; i < 20; i++) {
mHomeList.add(i, mHome);
}
}
private void populateUpdatedList() {
for (Home home : mHomeList) {
home.setGridListType(2);
}
}
private void populateGridList() {
for (Home home : mHomeList) {
home.setGridListType(5);
}
}
@Override
public void onTabGridClicked() {
populateGridList();
mManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
}
@Override
public void onTabListClicked() {
populateUpdatedList();
mManager = new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL);
}
}
EDIT
I've added notifyDataSetChanged();
instead of notifyItemChanged(selectedPosition);
and the change is instant but the second tab never looks selected and I can't swap between the first and the second one. I have to click the third one in order to get back to the first one. It's as if the tabs position is stuck.