/* * Copyright (C) 2016 Simon Vig Therkildsen * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.simonvt.cathode.ui.adapter; import android.content.Context; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import butterknife.BindView; import butterknife.ButterKnife; import java.util.ArrayList; import java.util.List; import net.simonvt.cathode.R; import timber.log.Timber; public class CategoryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public interface CategoryClickListener { void onCategoryClick(int category); } private class Category extends RecyclerView.AdapterDataObserver { final int category; final long categoryId; final long adapterId; RecyclerView.Adapter adapter; private int adapterCount; public Category(int category, long categoryId, long adapterId) { this.category = category; this.categoryId = categoryId; this.adapterId = adapterId; } public void setAdapter(RecyclerView.Adapter adapter) { Timber.d("Setting adapter"); if (this.adapter != null) { this.adapter.unregisterAdapterDataObserver(this); } this.adapter = adapter; adapter.registerAdapterDataObserver(this); onAdapterChanged(); } private void onAdapterChanged() { final int adapterCount = adapter.getItemCount(); Timber.d("onAdapterChanged: %d - %d", this.adapterCount, adapterCount); if (adapterCount == 0 && this.adapterCount > 0) { onHideCategory(this); } else if (this.adapterCount == 0 && adapterCount > 0) { onShowCategory(this); } this.adapterCount = adapterCount; } @Override public void onChanged() { onAdapterChanged(); } @Override public void onItemRangeChanged(int positionStart, int itemCount) { onAdapterChanged(); } @Override public void onItemRangeChanged(int positionStart, int itemCount, Object payload) { onAdapterChanged(); } @Override public void onItemRangeInserted(int positionStart, int itemCount) { onAdapterChanged(); } @Override public void onItemRangeRemoved(int positionStart, int itemCount) { onAdapterChanged(); } @Override public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { onAdapterChanged(); } } private static final int TYPE_CATEGORY = 0; private static final int TYPE_ITEMS = 1; List<Category> categories = new ArrayList<>(); private long nextId; private Context context; private CategoryClickListener clickListener; private boolean allCategoriesLoaded; public CategoryAdapter(Context context, CategoryClickListener clickListener) { this.context = context; this.clickListener = clickListener; } public void initCategory(int category) { categories.add(new Category(category, nextId++, nextId++)); } public void setAdapter(int category, RecyclerView.Adapter adapter) { for (Category c : categories) { if (category == c.category) { c.setAdapter(adapter); break; } } if (allCategoriesLoaded) { return; } for (Category c : categories) { if (c.adapter == null) { return; } } allCategoriesLoaded = true; notifyItemRangeInserted(0, getItemCount()); } private void onShowCategory(Category category) { Timber.d("onShowCategory"); if (allCategoriesLoaded) { final int position = getPositionOfCategory(category); notifyItemRangeInserted(position, 2); } } private void onHideCategory(Category category) { Timber.d("onHideCategory"); if (allCategoriesLoaded) { final int position = getPositionOfCategory(category); notifyItemRangeRemoved(position, 2); } } @Override public int getItemCount() { if (!allCategoriesLoaded) { return 0; } int count = 0; for (Category category : categories) { if (category.adapterCount > 0) { count += 2; } } return count; } private int getPositionOfCategory(Category category) { int position = 0; for (Category c : categories) { if (category == c) { return position; } if (c.adapterCount > 0) { position += 2; } } throw new IllegalStateException("No category found for category"); } private Category getCategoryForPosition(int position) { int offset = 0; for (Category category : categories) { if (category.adapterCount > 0) { offset += 2; if (position < offset) { return category; } } } throw new IllegalStateException("No category found for position " + position); } @Override public int getItemViewType(int position) { return position % 2 == 0 ? TYPE_CATEGORY : TYPE_ITEMS; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == TYPE_CATEGORY) { final View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.list_row_dashboard_category, parent, false); final CategoryViewHolder holder = new CategoryViewHolder(view); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final int position = holder.getAdapterPosition(); if (position != RecyclerView.NO_POSITION) { Category category = getCategoryForPosition(position); clickListener.onCategoryClick(category.category); } } }); return holder; } else { final RecyclerView recyclerView = (RecyclerView) LayoutInflater.from(parent.getContext()) .inflate(R.layout.list_row_dashboard_recyclerview, parent, false); recyclerView.setLayoutManager( new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)); ItemsViewHolder holder = new ItemsViewHolder(recyclerView); return holder; } } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { Category category = getCategoryForPosition(position); if (holder.getItemViewType() == TYPE_CATEGORY) { CategoryViewHolder cHolder = (CategoryViewHolder) holder; cHolder.category.setText(category.category); } else { ItemsViewHolder iHolder = (ItemsViewHolder) holder; iHolder.recyclerView.setAdapter(category.adapter); } } static final class CategoryViewHolder extends RecyclerView.ViewHolder { @BindView(R.id.category) TextView category; public CategoryViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } } static final class ItemsViewHolder extends RecyclerView.ViewHolder { RecyclerView recyclerView; public ItemsViewHolder(RecyclerView recyclerView) { super(recyclerView); this.recyclerView = recyclerView; } } }