de.mdxdave.materialbreadcrumbsnavigation.MaterialBreadcrumbsNavigation.java Source code

Java tutorial

Introduction

Here is the source code for de.mdxdave.materialbreadcrumbsnavigation.MaterialBreadcrumbsNavigation.java

Source

/**
 * Android Library for displaying Breadcrumbs Navigation in Material Design
 *
 * Copyright (C) 2015-2016 MDXDave
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package de.mdxdave.materialbreadcrumbsnavigation;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.ArrayList;

import de.mdxdave.material.breadcrumbs.R;

public class MaterialBreadcrumbsNavigation extends LinearLayout {

    private View view;
    private int textColor;
    private int indicatorColor;
    private int backgroundColor;
    private Context context;
    private HorizontalScrollView horizontalScrollView;
    private ViewGroup viewGroup;
    private FragmentManager fragmentManager;
    private int fragmentLayout;
    private boolean hasRootItem = false;
    private int active = 0;
    private ArrayList<NavigationItem> list;
    private BreadcrumbClickListener breadcrumbClickListener;

    public MaterialBreadcrumbsNavigation(Context context, AttributeSet attrs) {
        super(context, attrs);

        this.context = context;

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialBreadcrumbsNavigation, 0, 0);
        textColor = a.getColor(R.styleable.MaterialBreadcrumbsNavigation_textColor,
                ContextCompat.getColor(context, R.color.default_text));
        indicatorColor = a.getColor(R.styleable.MaterialBreadcrumbsNavigation_arrowColor,
                ContextCompat.getColor(context, R.color.default_indicator));
        backgroundColor = a.getColor(R.styleable.MaterialBreadcrumbsNavigation_backgroundColor,
                ContextCompat.getColor(context, R.color.default_background));
        a.recycle();

        setOrientation(LinearLayout.HORIZONTAL);
        setGravity(Gravity.CENTER_VERTICAL);

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.main_view, this, true);
        horizontalScrollView = (HorizontalScrollView) view.findViewById(R.id.horizontalScrollView);
        horizontalScrollView.setBackgroundColor(backgroundColor);
        viewGroup = (ViewGroup) findViewById(R.id.parent_view);

        list = new ArrayList<>();
    }

    public void setBackgroundColor(int Color) {
        horizontalScrollView.setBackgroundColor(Color);
    }

    public void setTextColor(int Color) {
        textColor = Color;
    }

    public int getItemCount() {
        return list.size();
    }

    public void addItem(NavigationItem item) {
        this.addItem(item, -1, false, true);
    }

    public void addItem(NavigationItem item, Boolean setActive) {
        this.addItem(item, -1, false, setActive);
    }

    public void setBreadcrumbClickListener(BreadcrumbClickListener breadcrumbClickListener) {
        this.breadcrumbClickListener = breadcrumbClickListener;
    }

    public void addRootItem(NavigationItem item) {
        addRootItem(item, true);
    }

    public void addRootItem(NavigationItem item, boolean setActive) {
        if (!hasRootItem) {
            this.hasRootItem = true;
            this.addItem(item, -1, true, setActive);
        } else {
            throw new IllegalStateException("Only one root item is allowed!");
        }
    }

    public void replaceRootItem(NavigationItem item) {
        replaceRootItem(item, false);
    }

    public void replaceRootItem(NavigationItem item, boolean setActive) {
        if (hasRootItem) {
            removeOnly(0);
            hasRootItem = false;
            addRootItem(item, setActive);
        } else {
            throw new IllegalStateException("There are no root item, so you can not replace it");
        }
    }

    public void replaceItem(int child, NavigationItem item) {
        replaceItem(child, item, false);
    }

    public void replaceItem(int child, NavigationItem item, boolean setActive) {
        if (child > list.size()) {
            throw new IndexOutOfBoundsException(
                    "There are only " + list.size() + " items, you can not replace the " + child + " item");
        } else if (child > 0) {
            removeOnly(child);
            addItem(item, child, false, setActive);
        } else {
            throw new IllegalStateException("Use replaceRootItem to replace the root item");
        }
    }

    public void removeAll() {
        list.clear();
        viewGroup.removeAllViews();
        hasRootItem = false;
    }

    private void addItem(final NavigationItem item, int position, boolean isRoot, boolean setActive) {
        LayoutInflater vi = (LayoutInflater) context.getApplicationContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View v = vi.inflate(R.layout.item_view, null);

        int last;
        if (isRoot) {
            last = 0;
            list.add(item);
        } else if (position == -1) {
            last = viewGroup.getChildCount();
            last = (last < 0) ? 0 : last;
            list.add(item);
        } else {
            last = position;
            list.set(position, item);
        }

        final TextView textView = (TextView) v.findViewById(R.id.breadcrumbnav_textView);
        textView.setTextColor(darkenColor(textColor));
        textView.setText(item.getTitle().toUpperCase());

        item.setId(last);

        final int finalLast = last;
        textView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                setActive(finalLast, false, true);
            }
        });

        ImageView imageView = (ImageView) v.findViewById(R.id.breadcrumbnav_imageView);
        imageView.setColorFilter(indicatorColor, PorterDuff.Mode.MULTIPLY);

        // Padding and root item
        if (isRoot) {
            imageView.setVisibility(View.GONE);
            int padding_left = 48;
            int padding_right = 12;
            int padding = 18;
            final float scale = getResources().getDisplayMetrics().density;
            int padding_left_px = (int) (padding_left * scale + 0.5f);
            int padding_right_px = (int) (padding_right * scale + 0.5f);
            int padding_px = (int) (padding * scale + 0.5f);
            textView.setPadding(padding_left_px, padding_px, padding_right_px, padding_px);
        }

        // Scroll to end

        final int finalLast1 = last;
        horizontalScrollView.post(new Runnable() {
            @Override
            public void run() {
                if (finalLast1 == viewGroup.getChildCount())
                    horizontalScrollView.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
            }
        });

        viewGroup.addView(v, last, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT));

        if (setActive || getCurrent() == position || list.size() == 0)
            setActive(last, true);
    }

    private void removeOnly(int child) {
        viewGroup.removeViewAt(child);
    }

    private void remove(int child) {
        int max = viewGroup.getChildCount();
        for (int i = max; i > child; i--) {
            Log.i("Remove", String.valueOf(i) + " from " + String.valueOf(max));
            removeOnly(i - 1);
            list.remove(i - 1);
        }
    }

    public void removeLast() {
        if (list.size() > 1) {
            remove(list.size() - 1);
        } else if (list.size() == 1) {
            throw new IllegalStateException("You can not remove the root item!");
        } else {
            throw new IndexOutOfBoundsException("There are only one root item, so there is nothing to remove");
        }

    }

    public void removeItem(int child) {
        if (child > list.size()) {
            throw new IndexOutOfBoundsException(
                    "There are only " + list.size() + " items, you can not remove the " + child + " one");
        } else if (child > 0) {
            remove(child);
            if (getCurrent() == child)
                setActive(child - 1, true);
        } else {
            throw new IllegalStateException("You can not remove the root item!");
        }
    }

    public boolean isActive(int child) {
        return (child == active);
    }

    public int getCurrent() {
        return active;
    }

    public NavigationItem getItem(int pos) {
        return list.get(pos);
    }

    public void replaceTitle(int pos, String title) {
        if (pos > list.size()) {
            throw new IndexOutOfBoundsException("There are only " + list.size()
                    + " items, you can not replace the title of the  " + pos + " one");
        }
        NavigationItem item = list.get(pos);
        item.setTitle(title);
        if (pos == 0)
            replaceRootItem(item);
        else
            replaceItem(pos, item);
    }

    public void setActive(int child) {
        setActive(child, true);
    }

    public void setActive(int child, boolean scrollTo, boolean clicked) {
        if (child > list.size()) {
            throw new IndexOutOfBoundsException(
                    "There are only " + list.size() + " items, you can not call the " + child + " one");
        }
        this.active = child;

        for (int i = 0; i < viewGroup.getChildCount(); i++) {
            Log.i("view", String.valueOf(i));
            ((TextView) viewGroup.getChildAt(i).findViewById(R.id.breadcrumbnav_textView))
                    .setTextColor(darkenColor(textColor));
        }

        try {
            final View v = viewGroup.getChildAt(child);
            TextView tv = (TextView) v.findViewById(R.id.breadcrumbnav_textView);
            tv.setTextColor(textColor);

            if (scrollTo)
                horizontalScrollView.post(new Runnable() {
                    @Override
                    public void run() {
                        horizontalScrollView.scrollTo(v.getLeft(), 0);
                    }
                });

            NavigationItem item = list.get(child);
            if (item.getFragment() != null) {
                Fragment fragment = item.getFragment();
                Bundle bn = fragment.getArguments();
                if (bn == null) {
                    bn = new Bundle();
                }
                bn.putInt("materialBreadcrumbsPosition", child - 1);
                try {
                    fragment.setArguments(bn);
                } catch (IllegalStateException e) {
                    // Fragment already active...
                }
                fragmentManager.beginTransaction().replace(fragmentLayout, fragment).commit();
            } else if (item.getObject() != null && clicked) {
                this.breadcrumbClickListener.onClick(item);
            }
        } catch (NullPointerException e) {
            e.printStackTrace();
        }

    }

    public void setActive(int child, boolean scrollTo) {
        setActive(child, scrollTo, false);
    }

    public void setupFragment(int layout, FragmentManager fm) {
        this.fragmentLayout = layout;
        this.fragmentManager = fm;
    }

    private static int modifyColor(int color, float factor) {
        int a = Color.alpha(color);
        int r = Color.red(color);
        int g = Color.green(color);
        int b = Color.blue(color);

        return Color.argb(a, Math.max((int) (r * factor), 0), Math.max((int) (g * factor), 0),
                Math.max((int) (b * factor), 0));
    }

    private int lightenColor(int color) {
        return modifyColor(color, 1.2f);
    }

    private int darkenColor(int color) {
        return modifyColor(color, 0.7f);
    }

}