All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.holoeverywhere.slider.SliderMenu Maven / Gradle / Ivy

The newest version!

package org.holoeverywhere.slider;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

import org.holoeverywhere.HoloEverywhere;
import org.holoeverywhere.LayoutInflater;
import org.holoeverywhere.ThemeManager;
import org.holoeverywhere.addon.AddonSlider.AddonSliderA;
import org.holoeverywhere.addon.IAddonThemes;
import org.holoeverywhere.app.Activity;
import org.holoeverywhere.app.Fragment;
import org.holoeverywhere.app.ListFragment;
import org.holoeverywhere.widget.ListView;
import org.holoeverywhere.widget.TextView;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.BadParcelableException;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentManager.OnBackStackChangedListener;
import android.support.v4.app.FragmentTransaction;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;

import com.actionbarsherlock.app.ActionBar;

public class SliderMenu implements OnBackStackChangedListener {
    public static enum SelectionBehavior {
        BackgroundWhenSelected, Default, OnlyBackground, OnlyHandler;
    }

    public static class SliderItem implements Parcelable {
        public static final Creator CREATOR = new Creator() {
            @Override
            public SliderItem createFromParcel(Parcel source) {
                try {
                    return new SliderItem(source);
                } catch (Exception e) {
                    throw new BadParcelableException(e);
                }
            }

            @Override
            public SliderItem[] newArray(int size) {
                return new SliderItem[size];
            }
        };
        private int mBackgroundColor = 0;
        private int mCustomLayout = 0;
        private Bundle mFragmentArguments;
        private Class mFragmentClass;
        private CharSequence mLabel;
        private WeakReference mLastFragment;
        private Fragment.SavedState mSavedState;
        private boolean mSaveState = true;
        private int mSelectionHandlerColor = 0;
        private SliderMenu mSliderMenu;
        private String mTag;
        private int mTextAppereance = 0;
        private int mTextAppereanceInverse = 0;

        public SliderItem() {
        }

        @SuppressWarnings("unchecked")
        protected SliderItem(Parcel source) throws Exception {
            String classname = source.readString();
            if (classname != null) {
                mFragmentClass = (Class) Class.forName(classname);
            }
            mSavedState = source.readParcelable(Fragment.SavedState.class.getClassLoader());
            mSaveState = source.readInt() == 1;
            mCustomLayout = source.readInt();
            mBackgroundColor = source.readInt();
            mSelectionHandlerColor = source.readInt();
            mTextAppereance = source.readInt();
            mTextAppereanceInverse = source.readInt();
            mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
        }

        @Override
        public int describeContents() {
            return 0;
        }

        public int getBackgroundColor() {
            return mBackgroundColor;
        }

        public int getCustomLayout() {
            return mCustomLayout;
        }

        public Bundle getFragmentArguments() {
            return mFragmentArguments;
        }

        public Class getFragmentClass() {
            return mFragmentClass;
        }

        public CharSequence getLabel() {
            return mLabel;
        }

        public int getSelectionHandlerColor() {
            return mSelectionHandlerColor;
        }

        public String getTag() {
            return mTag;
        }

        public int getTextAppereance() {
            return mTextAppereance;
        }

        public int getTextAppereanceInverse() {
            return mTextAppereanceInverse;
        }

        private void invalidate() {
            if (mSliderMenu != null) {
                mSliderMenu.invalidate();
            }
        }

        public boolean isSaveState() {
            return mSaveState;
        }

        public void setBackgroundColor(int backgroundColor) {
            mBackgroundColor = backgroundColor;
        }

        public void setCustomLayout(int customLayout) {
            mCustomLayout = customLayout;
        }

        public void setFragmentArguments(Bundle fragmentArguments) {
            mFragmentArguments = fragmentArguments;
        }

        public void setFragmentClass(Class fragmentClass) {
            if (mFragmentClass == fragmentClass) {
                return;
            }
            mFragmentClass = fragmentClass;
            mSavedState = null;
        }

        public void setLabel(CharSequence label) {
            mLabel = label;
            invalidate();
        }

        public void setSaveState(boolean saveState) {
            if (mSaveState == saveState) {
                return;
            }
            mSaveState = saveState;
            if (!saveState) {
                mSavedState = null;
            }
        }

        public void setSelectionHandlerColor(int selectionHandlerColor) {
            mSelectionHandlerColor = selectionHandlerColor;
        }

        public void setTag(String tag) {
            mTag = tag;
        }

        public void setTextAppereance(int textAppereance) {
            mTextAppereance = textAppereance;
        }

        public void setTextAppereanceInverse(int textAppereanceInverse) {
            mTextAppereanceInverse = textAppereanceInverse;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(mFragmentClass == null ? null : mFragmentClass.getName());
            dest.writeParcelable(mSaveState ? mSavedState : null, flags);
            dest.writeInt(mSaveState ? 1 : 0);
            dest.writeInt(mCustomLayout);
            dest.writeInt(mBackgroundColor);
            dest.writeInt(mSelectionHandlerColor);
            dest.writeInt(mTextAppereance);
            dest.writeInt(mTextAppereanceInverse);
            TextUtils.writeToParcel(mLabel, dest, flags);
        }
    }

    private final class SliderMenuAdapter extends BaseAdapter implements OnItemClickListener {
        private final int mDefaultTextAppearance;
        private final int mDefaultTextAppearanceInverse;
        private final LayoutInflater mLayoutInflater;

        private SliderMenuAdapter(Context context) {
            context = sThemes.context(context);
            mLayoutInflater = LayoutInflater.from(context);
            TypedArray a = context.obtainStyledAttributes(R.styleable.SliderMenu);
            mDefaultTextAppearance = a.getResourceId(
                    R.styleable.SliderMenu_textAppearanceSliderItem,
                    R.style.Holo_TextAppearance_Medium);
            mDefaultTextAppearanceInverse = a.getResourceId(
                    R.styleable.SliderMenu_textAppearanceSliderItemInverse,
                    R.style.Holo_TextAppearance_Medium_Inverse);
            a.recycle();
        }

        @Override
        public int getCount() {
            return mItems.size();
        }

        @Override
        public SliderItem getItem(int position) {
            return mItems.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public int getItemViewType(int position) {
            return getItem(position).mCustomLayout != 0 ? position
                    : Adapter.IGNORE_ITEM_VIEW_TYPE;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            final SliderItem item = getItem(position);
            if (convertView == null) {
                convertView = mLayoutInflater.inflate(item.mCustomLayout != 0 ? item.mCustomLayout
                        : R.layout.slider_menu_item, parent, false);
            }
            return bindView(item, convertView, mCurrentPage == position,
                    mDefaultTextAppearance, mDefaultTextAppearanceInverse);
        }

        @Override
        public void onItemClick(AdapterView parent, View view, int position, long id) {
            setCurrentPage(position, false);
        }
    }

    public static final int[] BLUE = new int[] {
            R.color.holo_blue_dark, R.color.holo_blue_light
    };
    public static final int[] GREEN = new int[] {
            R.color.holo_green_dark, R.color.holo_green_light
    };

    private static final String KEY_CURRENT_PAGE = ":slider:currentPage";

    public static final int[] ORANGE = new int[] {
            R.color.holo_orange_dark, R.color.holo_orange_light
    };

    public static final int[] PURPLE = new int[] {
            R.color.holo_purple_dark, R.color.holo_purple_light
    };

    public static final int[] RED = new int[] {
            R.color.holo_red_dark, R.color.holo_red_light
    };

    private static final IAddonThemes sThemes;
    public static final int THEME_FLAG;

    static {
        sThemes = new IAddonThemes();
        THEME_FLAG = sThemes.getThemeFlag();
        map(R.style.Holo_Internal_SliderTheme, R.style.Holo_Internal_SliderTheme_Light);
    }

    /**
     * Remap all SliderMenu themes
     */
    public static void map(int theme) {
        map(theme, theme, theme);
    }

    /**
     * Remap SliderMenu themes, splited by dark and light color scheme. For
     * mixed color scheme will be using light theme
     */
    public static void map(int darkTheme, int lightTheme) {
        map(darkTheme, lightTheme, lightTheme);
    }

    /**
     * Remap SliderMenu themes, splited by color scheme
     */
    public static void map(int darkTheme, int lightTheme, int mixedTheme) {
        sThemes.map(darkTheme, lightTheme, mixedTheme);
    }

    private static void setTextAppearance(TextView textView, int resid) {
        if (resid != 0) {
            textView.setTextAppearance(textView.getContext(), resid);
        }
    }

    private ActionBar mActionBar;
    private SliderMenuAdapter mAdapter;
    private final AddonSliderA mAddon;
    private int mCurrentPage = -1;
    private final FragmentManager mFragmentManager;
    private int mFuturePosition = -1;
    private boolean mHandleHomeKey;
    private boolean mIgnoreBackStack = false;
    private int mInitialPage = 0;
    private boolean mInverseTextColorWhenSelected = false;
    private final List mItems;
    private SelectionBehavior mSelectionBehavior = SelectionBehavior.Default;

    public SliderMenu(AddonSliderA addon) {
        mAddon = addon;
        mActionBar = addon.get().getSupportActionBar();
        mFragmentManager = mAddon.get().getSupportFragmentManager();
        mItems = new ArrayList();
    }

    public SliderItem add(CharSequence label, Class fragmentClass) {
        return add(label, fragmentClass, null, null);
    }

    public SliderItem add(CharSequence label, Class fragmentClass,
            Bundle fragmentArguments) {
        return add(label, fragmentClass, fragmentArguments, null);
    }

    public SliderItem add(CharSequence label, Class fragmentClass,
            Bundle fragmentArguments, int[] colors) {
        SliderItem item = new SliderItem();
        item.setLabel(label);
        item.setFragmentClass(fragmentClass);
        item.setFragmentArguments(fragmentArguments);
        if (colors != null && colors.length >= 2) {
            final Resources res = mAddon.get().getResources();
            item.setBackgroundColor(res.getColor(colors[0]));
            item.setSelectionHandlerColor(res.getColor(colors[1]));
        }
        return add(item);
    }

    public SliderItem add(CharSequence label, Class fragmentClass,
            int[] colors) {
        return add(label, fragmentClass, null, colors);
    }

    public SliderItem add(int label, Class fragmentClass) {
        return add(label, fragmentClass, null, null);
    }

    public SliderItem add(int label, Class fragmentClass,
            Bundle fragmentArguments) {
        return add(label, fragmentClass, fragmentArguments, null);
    }

    public SliderItem add(int label, Class fragmentClass,
            Bundle fragmentArguments, int[] colors) {
        return add(mAddon.get().getText(label), fragmentClass, fragmentArguments, colors);
    }

    public SliderItem add(int label, Class fragmentClass,
            int[] colors) {
        return add(label, fragmentClass, null, colors);
    }

    public SliderItem add(SliderItem item) {
        if (item.mSliderMenu != null) {
            throw new IllegalArgumentException("Item already has a parent: "
                    + item + " (" + item.mSliderMenu + ")");
        }
        item.mSliderMenu = this;
        mItems.add(item);
        notifyChanged();
        return item;
    }

    public SliderItem add(SliderItem item, int position) {
        if (item.mSliderMenu != null) {
            throw new IllegalArgumentException("Item already has a parent: "
                    + item + " (" + item.mSliderMenu + ")");
        }
        item.mSliderMenu = this;
        mItems.add(position, item);
        notifyChanged();
        return item;
    }

    public void bind(ListFragment listFragment) {
        bind(listFragment, null);
    }

    public void bind(ListFragment listFragment, Context context) {
        bind(listFragment.getListView(), context);
    }

    public void bind(ListView listView) {
        bind(listView, null);
    }

    public void bind(ListView listView, Context context) {
        if (mAdapter != null) {
            throw new IllegalStateException("No more than one view allowed");
        }
        mAdapter = new SliderMenuAdapter(context == null ? listView.getContext() : context);
        listView.setAdapter(mAdapter);
        listView.setOnItemClickListener(mAdapter);
        if (mFuturePosition >= 0) {
            setCurrentPage(mFuturePosition, true);
            mFuturePosition = -1;
        }
    }

    public void bindOnLeftPanel() {
        bindOnLeftPanel(null);
    }

    public void bindOnLeftPanel(Context context) {
        tryToBind(mAddon.getLeftView(), context);
    }

    public void bindOnRightPanel() {
        bindOnRightPanel(null);
    }

    public void bindOnRightPanel(Context context) {
        tryToBind(mAddon.getRightView(), context);
    }

    @SuppressWarnings("deprecation")
    public View bindView(SliderItem item, View view, boolean selected,
            int defaultTextAppearance, int defaultTextAppearanceInverse) {
        TextView labelView = (TextView) view.findViewById(android.R.id.text1);
        if (labelView != null) {
            labelView.setText(item.mLabel);
        }
        final int textAppereance = item.mTextAppereance != 0 ?
                item.mTextAppereance : defaultTextAppearance;
        final int textAppereanceInverse = item.mTextAppereanceInverse != 0 ?
                item.mTextAppereanceInverse : defaultTextAppearanceInverse;
        setTextAppearance(labelView,
                mInverseTextColorWhenSelected ? selected ? textAppereanceInverse
                        : textAppereance : textAppereance);
        if (mSelectionBehavior == null) {
            return view;
        }
        View selectionHandlerView = view.findViewById(R.id.selectionHandler);
        switch (mSelectionBehavior) {
            case Default:
                if (selected) {
                    view.setBackgroundColor(item.mBackgroundColor);
                    if (selectionHandlerView != null) {
                        selectionHandlerView.setBackgroundColor(item.mSelectionHandlerColor);
                    }
                } else {
                    view.setBackgroundDrawable(null);
                    if (selectionHandlerView != null) {
                        selectionHandlerView.setBackgroundDrawable(null);
                    }
                }
                break;
            case BackgroundWhenSelected:
                if (selectionHandlerView != null) {
                    selectionHandlerView.setBackgroundColor(item.mSelectionHandlerColor);
                }
                if (selected) {
                    view.setBackgroundColor(item.mBackgroundColor);
                } else {
                    view.setBackgroundDrawable(null);
                }
                break;
            case OnlyBackground:
                if (selected) {
                    view.setBackgroundColor(item.mBackgroundColor);
                } else {
                    view.setBackgroundDrawable(null);
                }
                break;
            case OnlyHandler:
                if (selectionHandlerView != null) {
                    if (selected) {
                        selectionHandlerView.setBackgroundColor(item.mSelectionHandlerColor);
                    } else {
                        selectionHandlerView.setBackgroundDrawable(null);
                    }
                }
                break;
        }
        return view;
    }

    protected void changePage(int position) {
        changePage(position, mItems.get(position));
    }

    private void changePage(int position, SliderItem item) {
        mIgnoreBackStack = true;
        if (mCurrentPage >= 0) {
            final SliderItem lastItem = mAdapter.getItem(mCurrentPage);
            final WeakReference ref = lastItem.mLastFragment;
            final Fragment fragment = ref == null ? null : ref.get();
            if (fragment != null && fragment.isAdded()) {
                if (!fragment.isDetached()) {
                    mFragmentManager.beginTransaction().detach(fragment).commit();
                    mFragmentManager.executePendingTransactions();
                }
                if (lastItem.mSaveState) {
                    lastItem.mSavedState = mFragmentManager.saveFragmentInstanceState(fragment);
                }
            }
        }
        mCurrentPage = position;
        mAdapter.notifyDataSetInvalidated();
        while (mFragmentManager.popBackStackImmediate()) {
        }
        final Fragment fragment = Fragment.instantiate(item.mFragmentClass);
        if (item.mSavedState != null) {
            fragment.setInitialSavedState(item.mSavedState);
        }
        if (item.mFragmentArguments != null) {
            item.mFragmentArguments.setClassLoader(HoloEverywhere.class.getClassLoader());
            fragment.setArguments(item.mFragmentArguments);
        }
        item.mLastFragment = new WeakReference(fragment);
        final String tag;
        if (item.mTag != null) {
            tag = item.mTag;
        } else {
            tag = "fragment-" + fragment.hashCode();
        }
        clearBackStack();
        replaceFragment(mFragmentManager, fragment, tag, false);
        mIgnoreBackStack = false;
    }

    private void clearBackStack() {
        while (mFragmentManager.popBackStackImmediate()) {
            ;
        }
    }

    public int getInitialPage() {
        return mInitialPage;
    }

    public SelectionBehavior getSelectionBehavior() {
        return mSelectionBehavior;
    }

    public int indexOfItem(SliderItem item) {
        return mItems.indexOf(item);
    }

    public void invalidate() {
        if (mAdapter != null) {
            mAdapter.notifyDataSetInvalidated();
        }
    }

    public boolean isHandleHomeKey() {
        return mHandleHomeKey;
    }

    public boolean isInverseTextColorWhenSelected() {
        return mInverseTextColorWhenSelected;
    }

    public void makeDefaultMenu() {
        makeDefaultMenu(false);
    }

    public void makeDefaultMenu(boolean useActionBarStyle) {
        final Activity activity = mAddon.get();
        makeDefaultMenu(useActionBarStyle ? activity.getSupportActionBarContext() : activity);
    }

    public void makeDefaultMenu(Context context) {
        setInverseTextColorWhenSelected(ThemeManager.getThemeType(mAddon.get()) != ThemeManager.LIGHT);
        ListFragment menuFragment = (ListFragment) mFragmentManager.findFragmentById(R.id.leftView);
        if (menuFragment == null) {
            menuFragment = (ListFragment) mFragmentManager.findFragmentById(R.id.rightView);
        }
        if (menuFragment == null) {
            throw new IllegalStateException("Couldn't find ListFragment for menu");
        }
        bind(menuFragment, context);
    }

    private void notifyChanged() {
        if (mAdapter != null) {
            mAdapter.notifyDataSetChanged();
        }
    }

    @Override
    public void onBackStackChanged() {
        if (mHandleHomeKey) {
            mActionBar.setDisplayHomeAsUpEnabled(mAddon.isAddonEnabled() ? true :
                    mFragmentManager.getBackStackEntryCount() > 0);
        }
        if (mIgnoreBackStack || mCurrentPage < 0 || mCurrentPage >= mItems.size()) {
            return;
        }
        SliderItem item = mItems.get(mCurrentPage);
        WeakReference ref = item.mLastFragment;
        Fragment fragment = ref == null ? null : ref.get();
        if (fragment == null || !item.mSaveState) {
            return;
        }
        if (fragment.isAdded() && fragment.isDetached() && !fragment.isVisible()) {
            item.mSavedState = mFragmentManager.saveFragmentInstanceState(fragment);
        }
    }

    public boolean onHomePressed() {
        if (mHandleHomeKey) {
            if (mAddon.isAddonEnabled()
                    && mFragmentManager.getBackStackEntryCount() == 0) {
                mAddon.toggle();
            } else {
                mAddon.get().onBackPressed();
            }
            return true;
        }
        return false;
    }

    public void onPostCreate(Bundle savedInstanceState) {
        if (savedInstanceState != null) {
            mCurrentPage = savedInstanceState.getInt(KEY_CURRENT_PAGE, 0);
        }
        mIgnoreBackStack = true;
        mAddon.get().getSupportFragmentManager().addOnBackStackChangedListener(this);
        onBackStackChanged();
        mIgnoreBackStack = false;
    }

    public void onResume() {
        if (mCurrentPage < 0 && mItems.size() > 0) {
            setCurrentPage(mInitialPage, true);
        }
    }

    public void onSaveInstanceState(Bundle outState) {
        outState.putInt(KEY_CURRENT_PAGE, mCurrentPage);
    }

    public void remove(int position) {
        mItems.remove(position).mSliderMenu = null;
        notifyChanged();
    }

    public void remove(SliderItem item) {
        if (mItems.remove(item)) {
            item.mSliderMenu = null;
        }
        notifyChanged();
    }

    public void replaceFragment(Fragment newFragment) {
        replaceFragment(newFragment, null, true);
    }

    public void replaceFragment(Fragment newFragment, String tag, boolean addToBackStack) {
        if (!addToBackStack) {
            clearBackStack();
        }
        replaceFragment(mFragmentManager, newFragment, tag, addToBackStack);
    }

    private void replaceFragment(FragmentManager fm, Fragment fragment, String tag,
            boolean addToBackStack) {
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.contentView, fragment, tag);
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
        if (addToBackStack) {
            ft.addToBackStack(tag);
            ft.commitAllowingStateLoss();
        } else {
            ft.commit();
        }
    }

    public void setCurrentPage(int position) {
        setCurrentPage(position, true);
    }

    private void setCurrentPage(int position, boolean force) {
        if (mAdapter == null) {
            mFuturePosition = position;
        }
        if (position < 0 || position >= mItems.size()) {
            throw new IndexOutOfBoundsException();
        }
        if (force || mCurrentPage != position
                || mAddon.get().getSupportFragmentManager().getBackStackEntryCount() > 0) {
            changePage(position, mAdapter.getItem(position));
            mCurrentPage = position;
        }
        if (mAddon.isAddonEnabled()) {
            mAddon.openContentViewDelayed(40);
        }
    }

    public void setHandleHomeKey(boolean handleHomeKey) {
        mHandleHomeKey = handleHomeKey;
    }

    public void setInitialPage(int initialPage) {
        mInitialPage = initialPage;
    }

    public void setInverseTextColorWhenSelected(boolean inverseTextColorWhenSelected) {
        mInverseTextColorWhenSelected = inverseTextColorWhenSelected;
    }

    public void setSelectionBehavior(SelectionBehavior selectionBehavior) {
        mSelectionBehavior = selectionBehavior;
    }

    private void tryToBind(View view, Context context) {
        if (view instanceof ListView) {
            bind((ListView) view, context);
            return;
        }
        final ListView listView = (ListView) view.findViewById(android.R.id.list);
        if (listView != null) {
            bind(listView, context);
            return;
        }
        throw new IllegalStateException("Couldn't find ListView on panel");
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy