Java tutorial
/* * Copyright 2015 Google Inc. * * 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 com.google.samples.apps.topeka.adapter; import android.app.Activity; import android.content.res.Resources; import android.databinding.DataBindingUtil; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.os.Build; import android.support.annotation.ColorRes; import android.support.annotation.NonNull; import android.support.v4.content.ContextCompat; import android.support.v4.graphics.drawable.DrawableCompat; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import com.google.samples.apps.topeka.R; import com.google.samples.apps.topeka.databinding.ItemCategoryBinding; import com.google.samples.apps.topeka.helper.ApiLevelHelper; import com.google.samples.apps.topeka.model.Category; import com.google.samples.apps.topeka.persistence.TopekaDatabaseHelper; import java.util.List; public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.ViewHolder> { public static final String DRAWABLE = "drawable"; private static final String ICON_CATEGORY = "icon_category_"; private final Resources mResources; private final String mPackageName; private final LayoutInflater mLayoutInflater; private final Activity mActivity; private List<Category> mCategories; private OnItemClickListener mOnItemClickListener; public interface OnItemClickListener { void onClick(View view, int position); } public CategoryAdapter(Activity activity) { mActivity = activity; mResources = mActivity.getResources(); mPackageName = mActivity.getPackageName(); mLayoutInflater = LayoutInflater.from(activity.getApplicationContext()); updateCategories(activity); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new ViewHolder((ItemCategoryBinding) DataBindingUtil.inflate(mLayoutInflater, R.layout.item_category, parent, false)); } @Override public void onBindViewHolder(final ViewHolder holder, final int position) { ItemCategoryBinding binding = holder.getBinding(); Category category = mCategories.get(position); binding.setCategory(category); binding.executePendingBindings(); setCategoryIcon(category, binding.categoryIcon); holder.itemView.setBackgroundColor(getColor(category.getTheme().getWindowBackgroundColor())); binding.categoryTitle.setTextColor(getColor(category.getTheme().getTextPrimaryColor())); binding.categoryTitle.setBackgroundColor(getColor(category.getTheme().getPrimaryColor())); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mOnItemClickListener.onClick(v, holder.getAdapterPosition()); } }); } @Override public long getItemId(int position) { return mCategories.get(position).getId().hashCode(); } @Override public int getItemCount() { return mCategories.size(); } public Category getItem(int position) { return mCategories.get(position); } /** * @see android.support.v7.widget.RecyclerView.Adapter#notifyItemChanged(int) * @param id Id of changed category. */ public final void notifyItemChanged(String id) { updateCategories(mActivity); notifyItemChanged(getItemPositionById(id)); } private int getItemPositionById(String id) { for (int i = 0; i < mCategories.size(); i++) { if (mCategories.get(i).getId().equals(id)) { return i; } } return -1; } public void setOnItemClickListener(OnItemClickListener onItemClickListener) { mOnItemClickListener = onItemClickListener; } private void setCategoryIcon(Category category, ImageView icon) { final int categoryImageResource = mResources.getIdentifier(ICON_CATEGORY + category.getId(), DRAWABLE, mPackageName); final boolean solved = category.isSolved(); if (solved) { Drawable solvedIcon = loadSolvedIcon(category, categoryImageResource); icon.setImageDrawable(solvedIcon); } else { icon.setImageResource(categoryImageResource); } } private void updateCategories(Activity activity) { mCategories = TopekaDatabaseHelper.getCategories(activity, true); } /** * Loads an icon that indicates that a category has already been solved. * * @param category The solved category to display. * @param categoryImageResource The category's identifying image. * @return The icon indicating that the category has been solved. */ private Drawable loadSolvedIcon(Category category, int categoryImageResource) { if (ApiLevelHelper.isAtLeast(Build.VERSION_CODES.LOLLIPOP)) { return loadSolvedIconLollipop(category, categoryImageResource); } return loadSolvedIconPreLollipop(category, categoryImageResource); } @NonNull private LayerDrawable loadSolvedIconLollipop(Category category, int categoryImageResource) { final Drawable done = loadTintedDoneDrawable(); final Drawable categoryIcon = loadTintedCategoryDrawable(category, categoryImageResource); Drawable[] layers = new Drawable[] { categoryIcon, done }; // ordering is back to front return new LayerDrawable(layers); } private Drawable loadSolvedIconPreLollipop(Category category, int categoryImageResource) { return loadTintedCategoryDrawable(category, categoryImageResource); } /** * Loads and tints a drawable. * * @param category The category providing the tint color * @param categoryImageResource The image resource to tint * @return The tinted resource */ private Drawable loadTintedCategoryDrawable(Category category, int categoryImageResource) { final Drawable categoryIcon = ContextCompat.getDrawable(mActivity, categoryImageResource).mutate(); return wrapAndTint(categoryIcon, category.getTheme().getPrimaryColor()); } /** * Loads and tints a check mark. * * @return The tinted check mark */ private Drawable loadTintedDoneDrawable() { final Drawable done = ContextCompat.getDrawable(mActivity, R.drawable.ic_tick); return wrapAndTint(done, android.R.color.white); } private Drawable wrapAndTint(Drawable done, @ColorRes int color) { Drawable compatDrawable = DrawableCompat.wrap(done); DrawableCompat.setTint(compatDrawable, getColor(color)); return compatDrawable; } /** * Convenience method for color loading. * * @param colorRes The resource id of the color to load. * @return The loaded color. */ private int getColor(@ColorRes int colorRes) { return ContextCompat.getColor(mActivity, colorRes); } static class ViewHolder extends RecyclerView.ViewHolder { private ItemCategoryBinding mBinding; public ViewHolder(ItemCategoryBinding binding) { super(binding.getRoot()); mBinding = binding; } public ItemCategoryBinding getBinding() { return mBinding; } } }