Back to project page ElyTheme.
The source code is released under:
GNU General Public License
If you think the Android project ElyTheme listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.afollestad.silk.fragments.list; /*from w ww. j a v a 2 s . c o m*/ import android.app.Fragment; import android.content.Context; import android.graphics.Typeface; import android.os.Bundle; import android.os.Handler; import android.util.TypedValue; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.animation.AnimationUtils; import android.widget.AdapterView; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; import com.afollestad.silk.R; import com.afollestad.silk.SilkComparable; import com.afollestad.silk.adapters.SilkAdapter; /** * @author Aidan Follestad (afollestad) */ public abstract class SilkListFragment<ItemType extends SilkComparable> extends Fragment { static final int INTERNAL_EMPTY_ID = 0x00ff0001; static final int INTERNAL_PROGRESS_CONTAINER_ID = 0x00ff0002; static final int INTERNAL_LIST_CONTAINER_ID = 0x00ff0003; final private Handler mHandler = new Handler(); final private Runnable mRequestFocus = new Runnable() { public void run() { mList.focusableViewAvailable(mList); } }; final private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View v, int position, long id) { onItemTapped(position, getAdapter().getItem(position), v); } }; private SilkAdapter<ItemType> mAdapter; private ListView mList; private View mEmptyView; private TextView mStandardEmptyView; private View mProgressContainer; private View mListContainer; protected boolean mListShown; private CharSequence mEmptyText; public SilkListFragment() { } public View getProgressContainer() { return mProgressContainer; } public final boolean isListShown() { return mListShown; } protected final void runOnUiThread(Runnable runnable) { if (getActivity() == null) return; getActivity().runOnUiThread(runnable); } protected ListView createListView() { return new ListView(getActivity()); } /** * Provide default implementation to return a simple list view. Subclasses * can override to replace with their own layout. If doing so, the * returned view hierarchy <em>must</em> have a ListView whose id * is {@link android.R.id#list android.R.id.list} and can optionally * have a sibling view id {@link android.R.id#empty android.R.id.empty} * that is to be shown when the list is empty. * <p/> * <p>If you are overriding this method with your own custom content, * consider including the standard layout {@link android.R.layout#list_content} * in your layout file, so that you continue to retain all of the standard * behavior of ListFragment. In particular, this is currently the only * way to have the built-in indeterminant progress state be shown. */ @SuppressWarnings("ResourceType") @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final Context context = getActivity(); FrameLayout root = new FrameLayout(context); // ------------------------------------------------------------------ LinearLayout pframe = new LinearLayout(context); pframe.setId(INTERNAL_PROGRESS_CONTAINER_ID); pframe.setOrientation(LinearLayout.VERTICAL); pframe.setVisibility(View.GONE); pframe.setGravity(Gravity.CENTER); pframe.setFitsSystemWindows(true); ProgressBar progress = new ProgressBar(context, null, android.R.attr.progressBarStyleLarge); pframe.addView(progress, new FrameLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); root.addView(pframe, new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); // ------------------------------------------------------------------ RelativeLayout lframe = new RelativeLayout(context); lframe.setId(INTERNAL_LIST_CONTAINER_ID); lframe.setFitsSystemWindows(true); TextView tv = new TextView(getActivity()); tv.setId(INTERNAL_EMPTY_ID); tv.setGravity(Gravity.CENTER); tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 22); tv.setTypeface(Typeface.create("sans-serif-light", Typeface.NORMAL)); int sidePadding = getActivity().getResources().getDimensionPixelSize(R.dimen.empty_text_padding); // tv.setPadding(sidePadding, 0, sidePadding, 0); RelativeLayout.LayoutParams tvParams = new RelativeLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); tvParams.addRule(RelativeLayout.CENTER_IN_PARENT); tvParams.leftMargin = sidePadding; tvParams.rightMargin = sidePadding; lframe.addView(tv, tvParams); ListView lv = createListView(); lv.setId(android.R.id.list); lv.setDrawSelectorOnTop(false); lframe.addView(lv, new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); root.addView(lframe, new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); // ------------------------------------------------------------------ root.setLayoutParams(new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); return root; } /** * Attach to list view once the view hierarchy has been created. */ @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); ensureList(); } /** * Detach from list view. */ @Override public void onDestroyView() { mHandler.removeCallbacks(mRequestFocus); mList = null; mListShown = false; mEmptyView = mProgressContainer = mListContainer = null; mStandardEmptyView = null; super.onDestroyView(); } /** * Set the currently selected list item to the specified * position with the adapter's data * * @param position */ public void setSelection(int position) { ensureList(); mList.setSelection(position); } /** * Get the position of the currently selected list item. */ public int getSelectedItemPosition() { ensureList(); return mList.getSelectedItemPosition(); } /** * Get the cursor row ID of the currently selected list item. */ public long getSelectedItemId() { ensureList(); return mList.getSelectedItemId(); } /** * Get the activity's list view widget. */ public ListView getListView() { ensureList(); return mList; } public TextView getStandardEmptyView() { ensureList(); return mStandardEmptyView; } /** * The default content for a ListFragment has a TextView that can * be shown when the list is empty. If you would like to have it * shown, call this method to supply the text it should use. */ public void setEmptyText(CharSequence text) { ensureList(); if (mStandardEmptyView == null) { throw new IllegalStateException("Can't be used with a custom content view"); } mStandardEmptyView.setText(text); if (mEmptyText == null) { mList.setEmptyView(mStandardEmptyView); } mEmptyText = text; } public void setListShown(boolean shown) { setListShown(shown, true); } /** * Like {@link #setListShown(boolean)}, but no animation is used when * transitioning from the previous state. */ public void setListShownNoAnimation(boolean shown) { setListShown(shown, false); } private void setListShown(boolean shown, boolean animate) { ensureList(); if (mProgressContainer == null) { throw new IllegalStateException("Can't be used with a custom content view"); } if (mListShown == shown) { return; } mListShown = shown; if (shown) { if (animate) { mProgressContainer.startAnimation(AnimationUtils.loadAnimation( getActivity(), android.R.anim.fade_out)); mListContainer.startAnimation(AnimationUtils.loadAnimation( getActivity(), android.R.anim.fade_in)); } else { mProgressContainer.clearAnimation(); mListContainer.clearAnimation(); } mProgressContainer.setVisibility(View.GONE); mListContainer.setVisibility(View.VISIBLE); } else { if (animate) { mProgressContainer.startAnimation(AnimationUtils.loadAnimation( getActivity(), android.R.anim.fade_in)); mListContainer.startAnimation(AnimationUtils.loadAnimation( getActivity(), android.R.anim.fade_out)); } else { mProgressContainer.clearAnimation(); mListContainer.clearAnimation(); } mProgressContainer.setVisibility(View.VISIBLE); mListContainer.setVisibility(View.GONE); } } @SuppressWarnings("ResourceType") private void ensureList() { if (mList != null) { return; } View root = getView(); if (root == null) { throw new IllegalStateException("Content view not yet created"); } if (root instanceof ListView) { mList = (ListView) root; } else { mStandardEmptyView = (TextView) root.findViewById(INTERNAL_EMPTY_ID); if (mStandardEmptyView == null) { mEmptyView = root.findViewById(android.R.id.empty); } else { mStandardEmptyView.setVisibility(View.GONE); } mProgressContainer = root.findViewById(INTERNAL_PROGRESS_CONTAINER_ID); mListContainer = root.findViewById(INTERNAL_LIST_CONTAINER_ID); View rawListView = root.findViewById(android.R.id.list); if (!(rawListView instanceof ListView)) { if (rawListView == null) { throw new RuntimeException( "Your content must have a ListView whose id attribute is " + "'android.R.id.list'" ); } throw new RuntimeException( "Content has view with id attribute 'android.R.id.list' " + "that is not a ListView class" ); } mList = (ListView) rawListView; if (mEmptyView != null) { mList.setEmptyView(mEmptyView); } else { if (getEmptyText() != 0 && mEmptyText == null) mEmptyText = getString(getEmptyText()); mStandardEmptyView.setText(mEmptyText); mList.setEmptyView(mStandardEmptyView); } } mListShown = true; mList.setOnItemClickListener(mOnClickListener); if (mAdapter == null) mAdapter = initializeAdapter(); if (mAdapter != null) { mList.setAdapter(mAdapter); } else { // We are starting without an adapter, so assume we won't // have our data right away and start with the progress indicator. if (mProgressContainer != null) { setListShown(false, false); } } mHandler.post(mRequestFocus); } /** * Gets the SilkAdapter used to add and remove items from the list. */ public SilkAdapter<ItemType> getAdapter() { return mAdapter; } /** * Only called once to cause inheriting classes to create a new SilkAdapter that can later be retrieved using * {#getAdapter}. */ protected abstract SilkAdapter<ItemType> initializeAdapter(); /** * Called when an item in the list is tapped by the user. * * @param index The index of the tapped item. * @param item The actual tapped item from the adapter. * @param view The view in the list that was tapped. */ protected abstract void onItemTapped(int index, ItemType item, View view); public abstract int getEmptyText(); }