/* * Copyright (C) 2016 Simon Vig Therkildsen * * 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 net.simonvt.cathode.ui.navigation; import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.graphics.Outline; import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.graphics.drawable.VectorDrawableCompat; import android.support.v4.widget.TextViewCompat; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewOutlineProvider; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.TextView; import java.util.ArrayList; import java.util.List; import net.simonvt.cathode.R; import net.simonvt.cathode.settings.Settings; import net.simonvt.cathode.settings.StartPage; import net.simonvt.cathode.ui.fragment.AbsAdapterFragment; import net.simonvt.cathode.widget.CircularShadowTransformation; import net.simonvt.cathode.widget.RemoteImageView; import net.simonvt.cathode.widget.RoundTransformation; public class NavigationFragment extends AbsAdapterFragment { public static final String TAG = "net.simonvt.cathode.ui.navigation.NavigationFragment"; private static final String STATE_SELECTED_POSITION = "net.simonvt.cathode.ui.navigation.NavigationFragment.selectedPosition"; public interface OnMenuClickListener { boolean onMenuItemClicked(int id); } private List<NavigationItem> menuItems = new ArrayList<>(); { menuItems.add(new MenuItem(R.id.menu_dashboard, R.string.navigation_dashboard, R.drawable.ic_nav_dashboard_24dp)); menuItems.add(new Divider()); menuItems.add(new CategoryItem(R.string.navigation_title_shows)); menuItems.add(new MenuItem(R.id.menu_shows_upcoming, R.string.navigation_shows_upcoming, R.drawable.ic_nav_upcoming_24dp)); menuItems.add(new MenuItem(R.id.menu_shows_watched, R.string.navigation_shows_watched, R.drawable.ic_nav_shows_watched_24dp)); menuItems.add(new MenuItem(R.id.menu_shows_collection, R.string.navigation_shows_collection, R.drawable.ic_nav_shows_collected_24dp)); menuItems.add(new MenuItem(R.id.menu_shows_watchlist, R.string.navigation_shows_watchlist, R.drawable.ic_nav_watchlist_24dp)); menuItems.add(new MenuItem(R.id.menu_shows_suggestions, R.string.navigation_shows_suggestions, R.drawable.ic_nav_suggestions_black_24dp)); menuItems.add(new Divider()); menuItems.add(new CategoryItem(R.string.navigation_title_movies)); menuItems.add(new MenuItem(R.id.menu_movies_watched, R.string.navigation_movies_watched, R.drawable.ic_nav_movies_watched_24dp)); menuItems.add(new MenuItem(R.id.menu_movies_collection, R.string.navigation_movies_collection, R.drawable.ic_nav_movies_collected_24dp)); menuItems.add(new MenuItem(R.id.menu_movies_watchlist, R.string.navigation_movies_watchlist, R.drawable.ic_nav_watchlist_24dp)); menuItems.add(new MenuItem(R.id.menu_movies_suggestions, R.string.navigation_movies_suggestions, R.drawable.ic_nav_suggestions_black_24dp)); menuItems.add(new Divider()); menuItems.add( new MenuItem(R.id.menu_lists, R.string.navigation_lists, R.drawable.ic_nav_list_24dp)); menuItems.add(new Divider()); menuItems.add( new MenuItem(R.id.menu_stats, R.string.navigation_stats, R.drawable.ic_nav_stats_24dp)); menuItems.add(new MenuItem(R.id.menu_settings, R.string.navigation_settings, R.drawable.ic_nav_settings_24dp)); } private OnMenuClickListener listener; private int selectedPosition = 1; private SharedPreferences settings; private NavigationAdapter adapter; @Override public void onAttach(Activity activity) { super.onAttach(activity); listener = (OnMenuClickListener) activity; } @Override public void onCreate(Bundle inState) { super.onCreate(inState); if (inState != null) { selectedPosition = inState.getInt(STATE_SELECTED_POSITION); } else { SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getActivity()); final String startPagePref = settings.getString(Settings.START_PAGE, null); StartPage startPage = StartPage.fromValue(startPagePref, StartPage.DASHBOARD); selectedPosition = getPositionForId(startPage.getMenuId()); } settings = PreferenceManager.getDefaultSharedPreferences(getActivity()); settings.registerOnSharedPreferenceChangeListener(settingsListener); String username = settings.getString(Settings.Profile.USERNAME, null); String avatar = settings.getString(Settings.Profile.AVATAR, null); adapter = new NavigationAdapter(getActivity(), menuItems); adapter.setUsername(username); adapter.setAvatar(avatar); setAdapter(adapter); } private int getPositionForId(long itemId) { for (int i = 0; i < menuItems.size(); i++) { NavigationItem item = menuItems.get(i); if (item instanceof MenuItem && ((MenuItem) item).id == itemId) { return 1 + i; } } return 1; } private SharedPreferences.OnSharedPreferenceChangeListener settingsListener = new SharedPreferences.OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (Settings.Profile.AVATAR.equals(key)) { String avatar = settings.getString(Settings.Profile.AVATAR, null); if (getAdapterView() != null) { final int firstPos = getAdapterView().getFirstVisiblePosition(); if (firstPos == 0 && getAdapterView().getChildCount() > 0) { ((RemoteImageView) getAdapterView().getChildAt(0) .getTag(R.id.profileIcon)).setImage(avatar); } } } if (Settings.Profile.USERNAME.equals(key)) { final String username = sharedPreferences.getString(Settings.Profile.USERNAME, null); adapter.setUsername(username); } } }; @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt(STATE_SELECTED_POSITION, selectedPosition); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle inState) { return inflater.inflate(R.layout.fragment_navigation, container, false); } @Override public void onViewCreated(View view, Bundle inState) { super.onViewCreated(view, inState); getAdapterView().setChoiceMode(AbsListView.CHOICE_MODE_SINGLE); getAdapterView().setItemChecked(selectedPosition, true); } @Override public void onDestroy() { settings.unregisterOnSharedPreferenceChangeListener(settingsListener); super.onDestroy(); } @Override protected void onItemClick(AdapterView l, View v, int position, long id) { MenuItem item = (MenuItem) getAdapter().getItem(position); if (listener.onMenuItemClicked(item.id)) { selectedPosition = position; } getAdapterView().setItemChecked(selectedPosition, true); } public void setSelectedId(long id) { selectedPosition = getPositionForId(id); adapter.notifyDataSetChanged(); if (getAdapterView() != null) { getAdapterView().setItemChecked(selectedPosition, true); } } private abstract static class NavigationItem { final int type; NavigationItem(int type) { this.type = type; } } private static class CategoryItem extends NavigationItem { final int title; CategoryItem(int title) { super(NavigationAdapter.TYPE_CATEGORY); this.title = title; } } private static class MenuItem extends NavigationItem { final int id; final int iconRes; final int title; MenuItem(int id, int title, int iconRes) { super(NavigationAdapter.TYPE_ITEM); this.id = id; this.title = title; this.iconRes = iconRes; } } private static class Divider extends NavigationItem { Divider() { super(NavigationAdapter.TYPE_DIVIDER); } } private class NavigationAdapter extends BaseAdapter { private static final int TYPE_HEADER = 0; private static final int TYPE_CATEGORY = 1; private static final int TYPE_ITEM = 2; private static final int TYPE_DIVIDER = 3; private Context context; private List<NavigationItem> items; private String username; private String avatar; NavigationAdapter(Context context, List<NavigationItem> items) { this.context = context; this.items = items; } public void setUsername(String username) { this.username = username; } public void setAvatar(String avatar) { this.avatar = avatar; } @Override public int getCount() { return 1 + items.size(); } @Override public NavigationItem getItem(int position) { return items.get(position - 1); } @Override public long getItemId(int position) { return position; } @Override public boolean areAllItemsEnabled() { return false; } @Override public boolean isEnabled(int position) { if (position == 0) { return false; } return getItem(position) instanceof MenuItem; } @Override public int getItemViewType(int position) { if (position == 0) { return TYPE_HEADER; } return getItem(position).type; } @Override public int getViewTypeCount() { return 4; } @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void setupCircularOutline(final RemoteImageView imageView) { imageView.setOutlineProvider(new ViewOutlineProvider() { @Override public void getOutline(View view, Outline outline) { final int width = view.getWidth(); final int height = view.getHeight(); float radius = Math.min(width / 2, height / 2); outline.setRoundRect(view.getPaddingLeft(), view.getPaddingRight(), width - view.getPaddingRight(), height - view.getPaddingBottom(), radius); outline.setAlpha(imageView.getFraction()); } }); } @Override public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; if (position == 0) { if (v == null) { v = LayoutInflater.from(context) .inflate(R.layout.fragment_navigation_header, parent, false); RemoteImageView headerBackground = (RemoteImageView) v.findViewById(R.id.headerBackground); headerBackground.setImage(R.drawable.drawer_header_background); v.setTag(R.id.username, v.findViewById(R.id.username)); final RemoteImageView profileIcon = (RemoteImageView) v.findViewById(R.id.profileIcon); profileIcon.addTransformation(new RoundTransformation()); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { setupCircularOutline(profileIcon); } else { final int dropShadowSize = (int) parent.getResources().getDimension(R.dimen.profileIconDropShadow); profileIcon.setResizeInsets(2 * dropShadowSize, 3 * dropShadowSize); profileIcon.addTransformation(new CircularShadowTransformation(dropShadowSize)); } v.setTag(R.id.profileIcon, profileIcon); } TextView username = (TextView) v.getTag(R.id.username); username.setText(this.username); RemoteImageView profileIcon = (RemoteImageView) v.getTag(R.id.profileIcon); profileIcon.setImage(avatar); return v; } NavigationItem item = getItem(position); if (item.type == TYPE_CATEGORY) { if (v == null) { v = LayoutInflater.from(context).inflate(R.layout.navigation_category, parent, false); } CategoryItem categoryItem = (CategoryItem) item; ((TextView) v).setText(categoryItem.title); } else if (item.type == TYPE_ITEM) { if (v == null) { v = LayoutInflater.from(context).inflate(R.layout.navigation_item, parent, false); } MenuItem menuItem = (MenuItem) item; ((TextView) v).setText(menuItem.title); VectorDrawableCompat d = VectorDrawableCompat.create(getResources(), menuItem.iconRes, null); TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(((TextView) v), d, null, null, null); } else { v = LayoutInflater.from(context).inflate(R.layout.navigation_divider, parent, false); } return v; } } }