com.github.andrewlord1990.materialandroid.component.grid.GridItemView.java Source code

Java tutorial

Introduction

Here is the source code for com.github.andrewlord1990.materialandroid.component.grid.GridItemView.java

Source

/*
 *  Copyright (C) 2016 Andrew Lord
 *
 *  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.github.andrewlord1990.materialandroid.component.grid;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.support.annotation.AttrRes;
import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.IntDef;
import android.support.annotation.LayoutRes;
import android.support.annotation.StringRes;
import android.support.annotation.StyleRes;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import com.github.andrewlord1990.materialandroid.R;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * A view that meets the Material Design specification for a grid item view. It supports many different variants,
 * containing one or two lines of text and an icon at the start (left) or end (right). When using two lines of text,
 * the lines of text can either have the same text size or different text sizes.
 */
public class GridItemView extends FrameLayout {

    public static final int VARIANT_ONE_LINE_TEXT = 0;
    public static final int VARIANT_ONE_LINE_TEXT_ICON = 1;
    public static final int VARIANT_TWO_LINE_TEXT = 2;
    public static final int VARIANT_TWO_LINE_TEXT_ICON = 3;
    public static final int ICON_GRAVITY_START = 0;
    public static final int ICON_GRAVITY_END = 1;

    private TextView primaryTextView;
    private TextView secondaryTextView;
    private ImageView iconView;

    private CharSequence primaryText;
    private CharSequence secondaryText;
    private Drawable icon;
    @ColorInt
    private int primaryTextColor;
    @ColorInt
    private int secondaryTextColor;
    private ColorStateList primaryTextColorStateList;
    private ColorStateList secondaryTextColorStateList;
    @GridItemVariant
    private int variant;
    @IconGravity
    private int iconGravity;

    /**
     * Create a grid item view using the settings from the style assigned to the theme attribute mdGridItemViewStyle.
     *
     * @param context The Context the view is running in, through which it can access the current theme, resources, etc.
     */
    public GridItemView(Context context) {
        this(context, null);
    }

    /**
     * Create a grid item view through XML inflation using settings from provided attributes and from the style assigned
     * to the theme attribute mdGridItemViewStyle.
     *
     * @param context The Context the view is running in, through which it can access the current theme, resources, etc.
     * @param attrs   The attributes of the XML tag that is inflating the view.
     */
    public GridItemView(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.mdGridItemViewStyle);
    }

    /**
     * Create a grid item view through XML inflation using settings from provided attributes and from the style assigned
     * to the specified theme attribute.
     *
     * @param context      The Context the view is running in, through which it can access the current theme, resources,
     *                     etc.
     * @param attrs        The attributes of the XML tag that is inflating the view.
     * @param defStyleAttr An attribute in the current theme that contains a reference to a style resource that supplies
     *                     default values for the view. Can be 0 to not look for defaults.
     */
    public GridItemView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        loadThemeAttributes(attrs, defStyleAttr, 0);
    }

    /**
     * Create a grid item view through XML inflation using settings from provided attributes, from the style assigned to
     * the specified theme attribute and from the specified style.
     *
     * @param context      The Context the view is running in, through which it can access the current theme, resources,
     *                     etc.
     * @param attrs        The attributes of the XML tag that is inflating the view.
     * @param defStyleAttr An attribute in the current theme that contains a reference to a style resource that supplies
     *                     default values for the view. Can be 0 to not look for defaults.
     * @param defStyleRes  A resource identifier of a style resource that supplies default values for the view, used
     *                     only if defStyleAttr is 0 or can not be found in the theme. Can be 0 to not look for defaults.
     */
    @TargetApi(21)
    public GridItemView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);

        loadThemeAttributes(attrs, defStyleAttr, defStyleRes);
    }

    private void loadThemeAttributes(AttributeSet attrs, @AttrRes int themeAttribute, @StyleRes int styleRes) {
        TypedArray typedAttrs = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.MDGridItemView,
                themeAttribute, styleRes);
        try {
            loadIcon(typedAttrs);
            loadVariant(typedAttrs);
            loadText(typedAttrs);
            loadTextColors(typedAttrs);
        } finally {
            typedAttrs.recycle();
        }
    }

    private void loadIcon(TypedArray typedAttrs) {
        Drawable icon = typedAttrs.getDrawable(R.styleable.MDGridItemView_md_grid_icon);
        setIcon(icon);
        @IconGravity
        int iconGravity = typedAttrs.getInt(R.styleable.MDGridItemView_md_grid_icon_gravity, ICON_GRAVITY_START);
        this.iconGravity = iconGravity;
    }

    private void loadVariant(TypedArray typedAttrs) {
        @GridItemVariant
        int variant = typedAttrs.getInt(R.styleable.MDGridItemView_md_grid_item_variant, VARIANT_ONE_LINE_TEXT);
        setVariant(variant);
    }

    private void loadText(TypedArray typedAttrs) {
        String primaryText = typedAttrs.getString(R.styleable.MDGridItemView_md_grid_text_primary);
        setPrimaryText(primaryText);

        String secondaryText = typedAttrs.getString(R.styleable.MDGridItemView_md_grid_text_secondary);
        setSecondaryText(secondaryText);
    }

    private void loadTextColors(TypedArray typedAttrs) {
        int primaryTextColor = typedAttrs.getColor(R.styleable.MDGridItemView_md_grid_text_primary_color, 0);
        if (primaryTextColor != 0) {
            setPrimaryTextColor(primaryTextColor);
        }

        int secondaryTextColor = typedAttrs.getColor(R.styleable.MDGridItemView_md_grid_text_secondary_color, 0);
        if (secondaryTextColor != 0) {
            setSecondaryTextColor(secondaryTextColor);
        }
    }

    @LayoutRes
    private int getLayoutFromVariant(@GridItemVariant int variant) {
        switch (variant) {
        case VARIANT_ONE_LINE_TEXT:
            return R.layout.md_grid_list_label_single_line;
        case VARIANT_ONE_LINE_TEXT_ICON:
            return getOneLineIconLayout();
        case VARIANT_TWO_LINE_TEXT:
            return R.layout.md_grid_list_label_two_line_same;
        case VARIANT_TWO_LINE_TEXT_ICON:
            return getTwoLineIconLayout();
        default:
            return R.layout.md_grid_list_label_single_line;
        }
    }

    @LayoutRes
    private int getOneLineIconLayout() {
        if (iconGravity == ICON_GRAVITY_END) {
            return R.layout.md_grid_list_label_single_line_icon_end;
        }
        return R.layout.md_grid_list_label_single_line_icon_start;
    }

    @LayoutRes
    private int getTwoLineIconLayout() {
        if (iconGravity == ICON_GRAVITY_END) {
            return R.layout.md_grid_list_label_two_line_same_icon_end;
        }
        return R.layout.md_grid_list_label_two_line_same_icon_start;
    }

    private void findChildViews() {
        primaryTextView = (TextView) findViewById(R.id.grid_list_label_line_1);
        secondaryTextView = (TextView) findViewById(R.id.grid_list_label_line_2);
        iconView = (ImageView) findViewById(R.id.grid_list_label_icon);
    }

    /**
     * Get the variant being displayed.
     *
     * @return The variant.
     */
    @GridItemVariant
    public int getVariant() {
        return variant;
    }

    /**
     * Set the variant to be displayed.
     *
     * @param variant The variant.
     */
    public void setVariant(@GridItemVariant int variant) {
        this.variant = variant;
        @LayoutRes
        int layout = getLayoutFromVariant(variant);
        removeAllViews();
        LayoutInflater inflater = LayoutInflater.from(getContext());
        inflater.inflate(layout, this);
        findChildViews();
        setTexts();
        setIcon(icon);
    }

    private void setTexts() {
        setPrimaryText(primaryText);
        setPrimaryTextColors();
        setSecondaryText(secondaryText);
        setSecondaryTextColors();
    }

    private void setPrimaryTextColors() {
        if (primaryTextColorStateList != null) {
            setPrimaryTextColor(primaryTextColorStateList);
        }
        if (primaryTextColor != 0) {
            setPrimaryTextColor(primaryTextColor);
        }
    }

    private void setSecondaryTextColors() {
        if (secondaryTextColorStateList != null) {
            setSecondaryTextColor(secondaryTextColorStateList);
        }
        if (secondaryTextColor != 0) {
            setSecondaryTextColor(secondaryTextColor);
        }
    }

    /**
     * Get the primary text (line 1).
     *
     * @return The primary text.
     */
    public CharSequence getPrimaryText() {
        return primaryTextView.getText();
    }

    /**
     * Set the primary text (line 1).
     *
     * @param textRes The primary text.
     */
    public void setPrimaryText(@StringRes int textRes) {
        setPrimaryText(getContext().getString(textRes));
    }

    /**
     * Set the primary text (line 1).
     *
     * @param text The primary text.
     */
    public void setPrimaryText(CharSequence text) {
        primaryText = text;
        primaryTextView.setText(text);
    }

    /**
     * Get the primary text color state list (line 1).
     *
     * @return The primary text color state list.
     */
    public ColorStateList getPrimaryTextColors() {
        return primaryTextView.getTextColors();
    }

    /**
     * Get the primary text color (line 1).
     *
     * @return The primary text color.
     */
    @ColorInt
    public int getCurrentPrimaryTextColor() {
        return primaryTextView.getCurrentTextColor();
    }

    /**
     * Set the primary text color (line 1).
     *
     * @param color The primary text color.
     */
    public void setPrimaryTextColor(ColorStateList color) {
        primaryTextColorStateList = color;
        primaryTextView.setTextColor(color);
    }

    /**
     * Set the primary text color (line 1).
     *
     * @param color The primary text color.
     */
    public void setPrimaryTextColor(@ColorInt int color) {
        primaryTextColor = color;
        primaryTextView.setTextColor(color);
    }

    /**
     * Set the primary text color (line 1).
     *
     * @param colorRes The primary text color.
     */
    public void setPrimaryTextColorRes(@ColorRes int colorRes) {
        setPrimaryTextColor(getColor(colorRes));
    }

    /**
     * Get the secondary text (line 2).
     *
     * @return The secondary text.
     */
    public CharSequence getSecondaryText() {
        if (secondaryTextView != null) {
            return secondaryTextView.getText();
        }
        return null;
    }

    /**
     * Set the secondary text (line 2).
     *
     * @param textRes The secondary text.
     */
    public void setSecondaryText(@StringRes int textRes) {
        setSecondaryText(getContext().getString(textRes));
    }

    /**
     * Set the secondary text (line 2).
     *
     * @param text The secondary text.
     */
    public void setSecondaryText(CharSequence text) {
        secondaryText = text;
        if (secondaryTextView != null) {
            secondaryTextView.setText(text);
        }
    }

    /**
     * Get the secondary text color state list (line 2).
     *
     * @return The secondary text color state list.
     */
    public ColorStateList getSecondaryTextColors() {
        if (secondaryTextView != null) {
            return secondaryTextView.getTextColors();
        }
        return null;
    }

    /**
     * Get the secondary text color (line 2).
     *
     * @return The secondary text color.
     */
    @ColorInt
    public int getCurrentSecondaryTextColor() {
        if (secondaryTextView != null) {
            return secondaryTextView.getCurrentTextColor();
        }
        return 0;
    }

    /**
     * Set the secondary text color (line 2).
     *
     * @param color The secondary text color.
     */
    public void setSecondaryTextColor(ColorStateList color) {
        secondaryTextColorStateList = color;
        if (secondaryTextView != null) {
            secondaryTextView.setTextColor(color);
        }
    }

    /**
     * Set the secondary text color (line 2).
     *
     * @param color The secondary text color.
     */
    public void setSecondaryTextColor(@ColorInt int color) {
        secondaryTextColor = color;
        if (secondaryTextView != null) {
            secondaryTextView.setTextColor(color);
        }
    }

    /**
     * Set the secondary text color (line 2).
     *
     * @param colorRes The secondary text color.
     */
    public void setSecondaryTextColorRes(@ColorRes int colorRes) {
        setSecondaryTextColor(getColor(colorRes));
    }

    /**
     * Get the icon being displayed.
     *
     * @return The displayed icon.
     */
    public Drawable getIcon() {
        if (iconView != null) {
            return iconView.getDrawable();
        }
        return null;
    }

    /**
     * Set the icon to display at the end (on the right).
     *
     * @param iconRes The icon to display.
     */
    public void setIcon(@DrawableRes int iconRes) {
        setIcon(ContextCompat.getDrawable(getContext(), iconRes));
    }

    /**
     * Set the icon to display at the end (on the right).
     *
     * @param icon The icon to display.
     */
    public void setIcon(Drawable icon) {
        this.icon = icon;
        if (iconView != null) {
            iconView.setImageDrawable(icon);
        }
    }

    /**
     * Get the icon gravity. Can be start (to display before the text - or on the left), or can be end (to display after
     * the text - or on the right).
     *
     * @return The gravity of the icon.
     */
    @IconGravity
    public int getIconGravity() {
        return iconGravity;
    }

    /**
     * Set the gravity of the icon. Can be start (to display before the text - or on the left), or can be end (to display
     * after the text - or on the right).
     *
     * @param iconGravity The gravity for the icon.
     */
    public void setIconGravity(@IconGravity int iconGravity) {
        this.iconGravity = iconGravity;
        setVariant(variant);
    }

    private int getColor(@ColorRes int colorRes) {
        return ContextCompat.getColor(getContext(), colorRes);
    }

    /**
     * Specifies that an int variable should only contain one of the grid item variant types.
     */
    @IntDef({ VARIANT_ONE_LINE_TEXT, VARIANT_ONE_LINE_TEXT_ICON, VARIANT_TWO_LINE_TEXT,
            VARIANT_TWO_LINE_TEXT_ICON })
    @Retention(RetentionPolicy.SOURCE)
    public @interface GridItemVariant {
    }

    /**
     * Specifies that an int variable should only contain one of the grid item icon gravity values.
     */
    @IntDef({ ICON_GRAVITY_START, ICON_GRAVITY_END })
    @Retention(RetentionPolicy.SOURCE)
    public @interface IconGravity {
    }

}