package be.digitalia.fosdem.fragments; import android.content.Context; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.FrameLayout; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.TextView; import be.digitalia.fosdem.widgets.ContentLoadingProgressBar; /** * Simpler ListFragment using ContentLoadingProgressBar. * * @author Christophe Beyls */ public class SmoothListFragment extends Fragment { private static final float DEFAULT_EMPTY_VIEW_PADDING_DIPS = 16f; static class ViewHolder { FrameLayout container; View emptyView; ListView listView; ContentLoadingProgressBar progress; } private final AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View v, int position, long id) { onListItemClick((ListView) parent, v, position, id); } }; private ViewHolder mHolder; private ListAdapter mAdapter; private boolean mListShown; /** * Override this method to provide a custom Empty View. * The default one is a TextView with some padding. */ @NonNull protected View onCreateEmptyView(LayoutInflater inflater, ViewGroup container, @Nullable Bundle savedInstanceState) { TextView textView = new TextView(inflater.getContext()); textView.setGravity(Gravity.CENTER); int textPadding = (int) (getResources().getDisplayMetrics().density * DEFAULT_EMPTY_VIEW_PADDING_DIPS + 0.5f); textView.setPadding(textPadding, textPadding, textPadding, textPadding); return textView; } @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { final Context context = inflater.getContext(); mHolder = new ViewHolder(); mHolder.container = new FrameLayout(context); mHolder.emptyView = onCreateEmptyView(inflater, mHolder.container, savedInstanceState); mHolder.emptyView.setId(android.R.id.empty); mHolder.container.addView(mHolder.emptyView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); mHolder.listView = new ListView(context); mHolder.listView.setId(android.R.id.list); mHolder.listView.setOnItemClickListener(mOnClickListener); mHolder.container.addView(mHolder.listView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); mHolder.progress = new ContentLoadingProgressBar(context, null, android.R.attr.progressBarStyleLarge); mHolder.progress.setId(android.R.id.progress); mHolder.progress.hide(); mHolder.container.addView(mHolder.progress, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER)); mHolder.container.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); mListShown = true; if (mAdapter != null) { setListAdapter(mAdapter); mHolder.listView.setEmptyView(mHolder.emptyView); } else { setListShown(false); } return mHolder.container; } @Override public void onDestroyView() { // Ensure the ListView is properly unregistered as an observer of the adapter mHolder.listView.setAdapter(null); mHolder = null; mListShown = false; super.onDestroyView(); } /** * This method will be called when an item in the list is selected. Subclasses should override. Subclasses can call * getListView().getItemAtPosition(position) if they need to access the data associated with the selected item. * * @param l The ListView where the click happened * @param v The view that was clicked within the ListView * @param position The position of the view in the list * @param id The row id of the item that was clicked */ public void onListItemClick(ListView l, View v, int position, long id) { } public void setListAdapter(ListAdapter adapter) { boolean hadNoAdapter = mAdapter == null; mAdapter = adapter; if (mHolder != null) { mHolder.listView.setAdapter(adapter); if (hadNoAdapter && !mListShown) { // The list was hidden, and previously didn't have an // adapter. It is now time to show it. setListShown(true); } } } /** * Get the fragments's ListView widget. */ public ListView getListView() { return mHolder.listView; } /** * The default content for a SmoothListFragment has a TextView that can be shown when the list is empty. * Call this method to supply the text it should use. */ public void setEmptyText(CharSequence text) { ((TextView) mHolder.emptyView).setText(text); } /** * Control whether the list is being displayed. You can make it not displayed if you are waiting for the initial data to show in it. During this time an * indeterminate progress indicator will be shown instead. * * @param shown If true, the list view is shown; if false, the progress indicator. The initial value is true. */ public void setListShown(boolean shown) { if (mListShown != shown) { if (shown) { mHolder.listView.setVisibility(View.VISIBLE); mHolder.listView.setEmptyView(mHolder.emptyView); mHolder.progress.hide(); } else { mHolder.listView.setEmptyView(null); mHolder.listView.setVisibility(View.GONE); mHolder.emptyView.setVisibility(View.GONE); mHolder.progress.show(); } mListShown = shown; } } /** * Get the ListAdapter associated with this activity's ListView. */ public ListAdapter getListAdapter() { return mAdapter; } }