package net.xpece.material.navigationdrawer.list;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.AttrRes;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import net.xpece.material.navigationdrawer.BuildConfig;
import net.xpece.material.navigationdrawer.R;
import net.xpece.material.navigationdrawer.descriptors.CompositeNavigationItemDescriptor;
import net.xpece.material.navigationdrawer.descriptors.GraphicNavigationItemDescriptor;
import net.xpece.material.navigationdrawer.descriptors.NavigationItemDescriptor;
import net.xpece.material.navigationdrawer.descriptors.NavigationSectionDescriptor;
import net.xpece.material.navigationdrawer.internal.Utils;
import java.util.ArrayList;
import java.util.List;
/**
* Created by pechanecjr on 14. 12. 2014.
*/
abstract class CompactNavigationListFragmentDelegate implements
AdapterView.OnItemClickListener, CompactNavigationListFragmentImpl {
public static final String TAG = CompactNavigationListFragmentDelegate.class.getSimpleName();
private static final NavigationListFragmentCallbacks DUMMY_CALLBACKS = new NavigationListFragmentCallbacks() {
@Override
public void onNavigationItemSelected(View view, int position, int id, NavigationItemDescriptor item) {
//
}
};
private NavigationListFragmentCallbacks mCallbacks = DUMMY_CALLBACKS;
private ListView mListView;
private CompactNavigationListAdapter mAdapter;
private boolean mReselectEnabled = true;
private int mLastSelected = -1;
private List<NavigationSectionDescriptor> mSections = new ArrayList<>(0);
private View mHeader = null;
private int mTheme;
private LayoutInflater mInflater;
public CompactNavigationListFragmentDelegate() {
}
public abstract Activity getActivity();
public abstract View getView();
@Override
public void onAttach(Activity activity) {
mCallbacks = (NavigationListFragmentCallbacks) activity;
}
@Override
public void onDetach() {
mCallbacks = DUMMY_CALLBACKS;
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putInt("mLastSelected", mLastSelected);
}
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
if (mTheme > 0) {
Context newContext = new ContextThemeWrapper(inflater.getContext(), mTheme);
inflater = inflater.cloneInContext(newContext);
}
mInflater = inflater;
View view = inflater.inflate(R.layout.mnd_list_compact, container, false);
mListView = (ListView) view.findViewById(R.id.mnd_list_compact);
return view;
}
@Override
public void onViewCreated(final View view, @Nullable Bundle savedInstanceState) {
mListView.setOnItemClickListener(this);
mListView.setSelector(Utils.getSelectorDrawable(view.getContext()));
if (savedInstanceState != null) {
mLastSelected = savedInstanceState.getInt("mLastSelected");
}
}
@Override
public void onDestroyView() {
mInflater = null;
mListView = null;
}
@Override
public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) {
TypedArray a = activity.obtainStyledAttributes(attrs, R.styleable.NavigationListFragment);
mTheme = a.getResourceId(R.styleable.NavigationListFragment_android_theme, 0);
a.recycle();
}
@Override
public LayoutInflater getLayoutInflater2() {
return mInflater;
}
@Override
public void setItems(List<? extends CompositeNavigationItemDescriptor> items) {
NavigationSectionDescriptor section = new NavigationSectionDescriptor().addItems(items);
List<NavigationSectionDescriptor> sections = new ArrayList<>(1);
sections.add(section);
setSections(sections);
}
/**
* Set all sections that would be shown in the navigation list except optional pinned section.
*
* @param sections
*/
@Override
public void setSections(List<NavigationSectionDescriptor> sections) {
mSections = sections;
updateSections();
}
private void updateSections() {
if (getView() == null) return;
mAdapter = new CompactNavigationListAdapter(mSections);
mAdapter.setReselectEnabled(mReselectEnabled);
mAdapter.setActivatedItem(mLastSelected);
mListView.setAdapter(mAdapter);
}
/**
* Use this method to set a header view. This header is selectable by default so you can use it as
* a no-op close drawer button. Alternatively you would set up an {@link android.view.View.OnClickListener}
* beforehand. <em>The header view is not managed by this class, it's completely in your hands.</em>
*
* @param view
*/
@Override
public void setHeaderView(View view, boolean clickable) {
if (view == mHeader) return;
if (mHeader != null) {
mListView.removeHeaderView(mHeader);
}
if (view != null) {
if (mListView != null) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
if (mListView.getAdapter() != null) mListView.setAdapter(null);
mListView.addHeaderView(view, null, clickable);
if (mAdapter != null) mListView.setAdapter(mAdapter);
} else {
mListView.addHeaderView(view, null, clickable);
}
}
}
mHeader = view;
}
/**
* Call this method when the source data set has changed, e.g. when you changed badges.
*/
@Override
public void notifyDataSetChanged() {
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
}
/**
* Use this to set a color as the navigation list background.
* Remember not to use translucent or transparent colors (pinned section has to have an opaque background).
*
* @param color
*/
@Override
public void setBackgroundColor(int color) {
if (getView() != null) {
getView().setBackgroundColor(color);
}
}
/**
* Use this to set a drawable as the navigation list background.
* Remember not to use vertical gradients (pinned section has to have an opaque background).
*
* @param drawable
*/
@Override
public void setBackground(Drawable drawable) {
if (getView() != null) {
Utils.setBackground(getView(), drawable);
}
}
/**
* Use this to resolve a drawable or color resource ID as a drawable and set it as the navigation list background.
* Remember not to use vertical gradients (pinned section has to have an opaque background).
*
* @param resource
*/
@Override
public void setBackgroundResource(@DrawableRes @ColorRes int resource) {
if (getView() != null) {
getView().setBackgroundResource(resource);
}
}
/**
* Use this to resolve an attribute as a drawable and set it as the navigation list background.
* Remember not to use vertical gradients (pinned section has to have an opaque background).
*
* @param attr
*/
@Override
public void setBackgroundAttr(@AttrRes int attr) {
if (getView() != null) {
Drawable d = Utils.getDrawableAttr(getView().getContext(), attr);
setBackground(d);
}
}
/**
* Use this method for marking selected item from outside. Typically you call this in
* {@link android.app.Activity#onPostCreate(android.os.Bundle)} after you determine which
* section was selected previously or by default.
*
* @param id
*/
@Override
public void setSelectedItem(int id) {
if (mAdapter != null) {
int position = mAdapter.getPositionById(id);
trySelectPosition(position);
} else {
throw new IllegalStateException("No adapter yet!");
}
}
private void trySelectPosition(final int itemPosition) {
final int listPosition = itemPosition + mListView.getHeaderViewsCount();
// if (listPosition == mLastSelected) return;
if (itemPosition < 0) {
mListView.setItemChecked(listPosition, false);
mAdapter.setActivatedItem(-1);
mLastSelected = -1;
return;
}
CompositeNavigationItemDescriptor item = (CompositeNavigationItemDescriptor) mAdapter.getItem(itemPosition);
if (item != null && item.isSticky()) {
mListView.setItemChecked(mLastSelected, false);
mListView.setItemChecked(listPosition, true);
mAdapter.setActivatedItem(itemPosition);
mLastSelected = listPosition;
} else {
selectPreviousPosition(listPosition);
}
}
private void selectPreviousPosition(int deselect) {
mListView.setItemChecked(deselect, false);
mListView.setItemChecked(mLastSelected, true);
}
/**
* @param parent
* @param view
* @param position
* @param id
*/
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
GraphicNavigationItemDescriptor item = (GraphicNavigationItemDescriptor) parent.getItemAtPosition(position);
onItemClick(view, position, item != null ? item.getId() : (int) id, item);
}
private void onItemClick(View view, int position, int id, GraphicNavigationItemDescriptor item) {
// header views and items from pinned section are not sticky, don't even try
if (position >= 0 && position < mListView.getHeaderViewsCount()) {
// || position > mListView.getHeaderViewsCount() + mAdapter.getCount()) {
selectPreviousPosition(position);
} else {
final int itemPosition = position - mListView.getHeaderViewsCount();
trySelectPosition(itemPosition);
}
mCallbacks.onNavigationItemSelected(view, position, id, item);
}
public void setReselectEnabled(boolean reselectEnabled) {
mReselectEnabled = reselectEnabled;
if (mAdapter != null) {
mAdapter.setReselectEnabled(reselectEnabled);
}
}
private static void timber(String s) {
if (BuildConfig.DEBUG) Log.d(TAG, s);
}
}