package org.commcare.adapters; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.StateListDrawable; import android.os.Build; import android.support.v4.content.ContextCompat; import android.support.v7.widget.RecyclerView; import android.util.StateSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import org.commcare.dalvik.R; import org.commcare.views.ViewUtil; import java.util.List; /** * Inflation and binding of square cards used on home screen and other places. * * @author Phillip Mates (pmates@dimagi.com). */ abstract class SquareButtonAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { final Context context; private static final int TYPE_BUTTON = 0; SquareButtonAdapter(Context context) { this.context = context; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { final LayoutInflater inflater = LayoutInflater.from(parent.getContext()); if (viewType == TYPE_BUTTON) { View layoutView = inflater.inflate(R.layout.square_card, parent, false); return new SquareButtonViewHolder(layoutView); } else { throw new RuntimeException("No " + viewType + " view type exists"); } } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int i) { if (holder instanceof SquareButtonViewHolder) { bindCard((SquareButtonViewHolder)holder, i, null); } else { throw new RuntimeException("Unable to bind ViewHolder of type: " + holder.getClass()); } } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int i, List<Object> payload) { if (holder instanceof SquareButtonViewHolder) { bindCard((SquareButtonViewHolder)holder, i, payload); } else { throw new RuntimeException("Unable to bind ViewHolder of type: " + holder.getClass()); } } private void bindCard(SquareButtonViewHolder squareButtonViewHolder, int i, List<Object> payload) { HomeCardDisplayData cardDisplayData = getItem(i); String notificationText = null; if (payload != null) { notificationText = getFirstPayloadString(payload); } cardDisplayData.textSetter.update(cardDisplayData, squareButtonViewHolder, context, notificationText); setupViewHolder(context, cardDisplayData, squareButtonViewHolder); } /** * Get nth data element in adapter. */ protected abstract HomeCardDisplayData getItem(int position); /** * Get 1st string in payload list, which is constructed from payloads * provided on calls to notify item/data set changed. */ private static String getFirstPayloadString(List<Object> payloadList) { String lastPayloadString = null; for (Object entry : payloadList) { if (entry instanceof String) { lastPayloadString = (String)entry; } } return lastPayloadString; } private static void setupViewHolder(Context context, HomeCardDisplayData cardDisplayData, SquareButtonViewHolder squareButtonViewHolder) { final Drawable buttonDrawable = ContextCompat.getDrawable(context, cardDisplayData.imageResource); squareButtonViewHolder.imageView.setImageDrawable(buttonDrawable); squareButtonViewHolder.cardView.setOnClickListener(cardDisplayData.listener); StateListDrawable bgDrawable = bgDrawStates(context, cardDisplayData.bgColor); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { squareButtonViewHolder.cardView.setBackground(bgDrawable); } else { squareButtonViewHolder.cardView.setBackgroundDrawable(bgDrawable); } } /** * Build drawable with default state being the provided color resource, * pressed color state being that color with less saturation, and disabled * state being gray. */ private static StateListDrawable bgDrawStates(Context context, int bgColorResource) { ColorDrawable disabledColor = new ColorDrawable(context.getResources().getColor(R.color.grey)); ColorDrawable colorDrawable = new ColorDrawable(context.getResources().getColor(bgColorResource)); ColorDrawable pressedBackground = desaturateColor(colorDrawable); StateListDrawable sld = new StateListDrawable(); sld.addState(new int[]{-android.R.attr.state_enabled}, disabledColor); sld.addState(new int[]{android.R.attr.state_pressed}, pressedBackground); sld.addState(StateSet.WILD_CARD, colorDrawable); return sld; } private static ColorDrawable desaturateColor(ColorDrawable colorDrawable) { float[] hsvOutput = new float[3]; int color = ViewUtil.getColorDrawableColor(colorDrawable); Color.colorToHSV(color, hsvOutput); hsvOutput[2] = (float)(hsvOutput[2] / 1.5); return new ColorDrawable(Color.HSVToColor(hsvOutput)); } @Override public int getItemViewType(int position) { return TYPE_BUTTON; } }