From f606578467ac3d13f8b771056b64ae3d13aebafc Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Fri, 4 Sep 2015 15:25:02 +0300 Subject: [PATCH] #10 Support cursor adapters --- .../utils/CircularContactView.java | 1 + .../utils/ContactsCursorAdapter.java | 54 ++++++++ .../IndexedPinnedHeaderListViewAdapter.java | 2 +- .../lb/library/PinnedHeaderContainer.java | 7 + ...BasePinnedHeaderCursorListViewAdapter.java | 127 ++++++++++++++++++ ...exedPinnedHeaderCursorListViewAdapter.java | 60 +++++++++ ...ablePinnedHeaderCursorListViewAdapter.java | 34 +++++ 7 files changed, 284 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/lb/listviewvariants/utils/ContactsCursorAdapter.java create mode 100644 library/src/main/java/lb/library/PinnedHeaderContainer.java create mode 100644 library/src/main/java/lb/library/cursor/BasePinnedHeaderCursorListViewAdapter.java create mode 100644 library/src/main/java/lb/library/cursor/IndexedPinnedHeaderCursorListViewAdapter.java create mode 100644 library/src/main/java/lb/library/cursor/SearchablePinnedHeaderCursorListViewAdapter.java diff --git a/app/src/main/java/lb/listviewvariants/utils/CircularContactView.java b/app/src/main/java/lb/listviewvariants/utils/CircularContactView.java index b128ce5..f630607 100644 --- a/app/src/main/java/lb/listviewvariants/utils/CircularContactView.java +++ b/app/src/main/java/lb/listviewvariants/utils/CircularContactView.java @@ -11,6 +11,7 @@ import android.support.v4.graphics.drawable.RoundedBitmapDrawable; import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory; import android.util.AttributeSet; +import android.util.TypedValue; import android.view.Gravity; import android.widget.FrameLayout; import android.widget.ImageView; diff --git a/app/src/main/java/lb/listviewvariants/utils/ContactsCursorAdapter.java b/app/src/main/java/lb/listviewvariants/utils/ContactsCursorAdapter.java new file mode 100644 index 0000000..4925cdc --- /dev/null +++ b/app/src/main/java/lb/listviewvariants/utils/ContactsCursorAdapter.java @@ -0,0 +1,54 @@ +package lb.listviewvariants.utils; + +import android.content.Context; +import android.database.Cursor; +import android.provider.ContactsContract.Contacts; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import lb.library.cursor.SearchablePinnedHeaderCursorListViewAdapter; +import lb.listviewvariants.R; + +public class ContactsCursorAdapter extends SearchablePinnedHeaderCursorListViewAdapter { + + public ContactsCursorAdapter(Context context) { + super(context, getQuery(context), false); + } + + private static Cursor getQuery(Context context) { + return context.getContentResolver().query(Contacts.CONTENT_URI, new String[]{"_id", "display_name"}, null, null, "display_name asc"); + } + + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + final View inflated = LayoutInflater.from(context).inflate(R.layout.listview_item, null); + final ViewHolder holder = new ViewHolder(); + holder.name = (TextView) inflated.findViewById(R.id.listview_item__friendNameTextView); + holder.headerView = (TextView) inflated.findViewById(R.id.header_text); + inflated.setTag(holder); + return inflated; + } + + @Override + protected TextView findHeaderView(View itemView) { + return ((ViewHolder) itemView.getTag()).headerView; + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + super.bindView(view, context, cursor); + final String name = cursor.getString(1); + ((ViewHolder) view.getTag()).name.setText(name); + } + + @Override + protected Cursor getFilterCursor(CharSequence constraint) { + return null; + } + + private static class ViewHolder { + public TextView name; + public TextView headerView; + } +} diff --git a/library/src/main/java/lb/library/IndexedPinnedHeaderListViewAdapter.java b/library/src/main/java/lb/library/IndexedPinnedHeaderListViewAdapter.java index 0b14a06..931b66a 100644 --- a/library/src/main/java/lb/library/IndexedPinnedHeaderListViewAdapter.java +++ b/library/src/main/java/lb/library/IndexedPinnedHeaderListViewAdapter.java @@ -6,7 +6,7 @@ import android.view.View; import android.widget.TextView; -public abstract class IndexedPinnedHeaderListViewAdapter extends BasePinnedHeaderListViewAdapter +public abstract class IndexedPinnedHeaderListViewAdapter extends BasePinnedHeaderListViewAdapter implements PinnedHeaderContainer { private int _pinnedHeaderBackgroundColor; private int _pinnedHeaderTextColor; diff --git a/library/src/main/java/lb/library/PinnedHeaderContainer.java b/library/src/main/java/lb/library/PinnedHeaderContainer.java new file mode 100644 index 0000000..0d4c3fc --- /dev/null +++ b/library/src/main/java/lb/library/PinnedHeaderContainer.java @@ -0,0 +1,7 @@ +package lb.library; + +public interface PinnedHeaderContainer { + + void setPinnedHeaderBackgroundColor(final int pinnedHeaderBackgroundColor); + void setPinnedHeaderTextColor(final int pinnedHeaderTextColor); +} diff --git a/library/src/main/java/lb/library/cursor/BasePinnedHeaderCursorListViewAdapter.java b/library/src/main/java/lb/library/cursor/BasePinnedHeaderCursorListViewAdapter.java new file mode 100644 index 0000000..6141c99 --- /dev/null +++ b/library/src/main/java/lb/library/cursor/BasePinnedHeaderCursorListViewAdapter.java @@ -0,0 +1,127 @@ +package lb.library.cursor; + +import android.content.Context; +import android.database.Cursor; +import android.view.View; +import android.widget.AbsListView; +import android.widget.AbsListView.OnScrollListener; +import android.widget.AlphabetIndexer; +import android.widget.CursorAdapter; +import android.widget.SectionIndexer; +import android.widget.TextView; +import lb.library.PinnedHeaderListView; + +public abstract class BasePinnedHeaderCursorListViewAdapter extends CursorAdapter implements SectionIndexer, OnScrollListener, PinnedHeaderListView.PinnedHeaderAdapter { + + private SectionIndexer mSectionIndexer; + private boolean mHeaderViewVisible = true; + + public BasePinnedHeaderCursorListViewAdapter(Context context, Cursor c, boolean autoRequery) { + super(context, c, autoRequery); + setSectionIndexer(new AlphabetIndexer(c, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")); + } + + public void setSectionIndexer(final SectionIndexer sectionIndexer) { + mSectionIndexer = sectionIndexer; + } + + public abstract CharSequence getSectionTitle(int sectionIndex); + protected abstract TextView findHeaderView(View itemView); + + + @Override + public void bindView(View view, Context context, Cursor cursor) { + bindSectionHeader(findHeaderView(view), null, cursor.getPosition()); + } + + @Override + public int getPinnedHeaderState(final int position) { + if (mSectionIndexer == null || getCount() == 0 || !mHeaderViewVisible) { + return PINNED_HEADER_GONE; + } + + if (position < 0) { + return PINNED_HEADER_GONE; + } + // The header should get pushed up if the top item shown + // is the last item in a section for a particular letter. + final int section = getSectionForPosition(position); + final int nextSectionPosition = getPositionForSection(section + 1); + if (nextSectionPosition != -1 && position == nextSectionPosition - 1) { + return PINNED_HEADER_PUSHED_UP; + } + return PINNED_HEADER_VISIBLE; + } + + @Override + public void onScroll(final AbsListView view, final int firstVisibleItem, final int visibleItemCount, + final int totalItemCount) { + ((PinnedHeaderListView) view).configureHeaderView(firstVisibleItem); + } + + @Override + public void onScrollStateChanged(final AbsListView arg0, final int arg1) { + } + + @Override + public int getPositionForSection(final int sectionIndex) { + if (mSectionIndexer == null) { + return -1; + } + return mSectionIndexer.getPositionForSection(sectionIndex); + } + + @Override + public int getSectionForPosition(final int position) { + if (mSectionIndexer == null) { + return -1; + } + return mSectionIndexer.getSectionForPosition(position); + } + + @Override + public Object[] getSections() { + if (mSectionIndexer == null) { + return new String[]{" "}; + } + return mSectionIndexer.getSections(); + } + + @Override + public long getItemId(final int position) { + return position; + } + + protected final SectionIndexer getSectionIndexer() { + return mSectionIndexer; + } + + protected void bindSectionHeader(final TextView headerView, final View dividerView, final int position) { + final int sectionIndex = getSectionForPosition(position); + if (getPositionForSection(sectionIndex) == position) { + final CharSequence title = getSectionTitle(sectionIndex); + headerView.setText(title); + headerView.setVisibility(View.VISIBLE); + if (dividerView != null) { + dividerView.setVisibility(View.GONE); + } + } else { + headerView.setVisibility(View.GONE); + if (dividerView != null) { + dividerView.setVisibility(View.VISIBLE); + } + } + // move the divider for the last item in a section + if (dividerView != null) { + if (getPositionForSection(sectionIndex + 1) - 1 == position) { + dividerView.setVisibility(View.GONE); + } else { + dividerView.setVisibility(View.VISIBLE); + } + } + + if (!mHeaderViewVisible) { + headerView.setVisibility(View.GONE); + } + } +} diff --git a/library/src/main/java/lb/library/cursor/IndexedPinnedHeaderCursorListViewAdapter.java b/library/src/main/java/lb/library/cursor/IndexedPinnedHeaderCursorListViewAdapter.java new file mode 100644 index 0000000..013a2f1 --- /dev/null +++ b/library/src/main/java/lb/library/cursor/IndexedPinnedHeaderCursorListViewAdapter.java @@ -0,0 +1,60 @@ +package lb.library.cursor; + +import android.content.Context; +import android.database.Cursor; +import android.graphics.Color; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; +import android.view.View; +import android.widget.TextView; +import lb.library.PinnedHeaderContainer; + +public abstract class IndexedPinnedHeaderCursorListViewAdapter extends BasePinnedHeaderCursorListViewAdapter implements PinnedHeaderContainer { + + private int _pinnedHeaderBackgroundColor; + private int _pinnedHeaderTextColor; + + public IndexedPinnedHeaderCursorListViewAdapter(Context context, Cursor c, boolean autoRequery) { + super(context, c, autoRequery); + } + + public void setPinnedHeaderBackgroundColor(final int pinnedHeaderBackgroundColor) { + _pinnedHeaderBackgroundColor = pinnedHeaderBackgroundColor; + } + + public void setPinnedHeaderTextColor(final int pinnedHeaderTextColor) { + _pinnedHeaderTextColor = pinnedHeaderTextColor; + } + + @Override + public CharSequence getSectionTitle(final int sectionIndex) { + return getSections()[sectionIndex].toString(); + } + + @Override + public void configurePinnedHeader(final View v, final int position, final int alpha) { + final TextView header = (TextView) v; + final int sectionIndex = getSectionForPosition(position); + final Object[] sections = getSections(); + if (sections != null && sections.length != 0) { + final CharSequence title = getSectionTitle(sectionIndex); + header.setText(title); + } + if (VERSION.SDK_INT < VERSION_CODES.HONEYCOMB) + if (alpha == 255) { + header.setBackgroundColor(_pinnedHeaderBackgroundColor); + header.setTextColor(_pinnedHeaderTextColor); + } else { + header.setBackgroundColor(Color.argb(alpha, Color.red(_pinnedHeaderBackgroundColor), + Color.green(_pinnedHeaderBackgroundColor), Color.blue(_pinnedHeaderBackgroundColor))); + header.setTextColor(Color.argb(alpha, Color.red(_pinnedHeaderTextColor), + Color.green(_pinnedHeaderTextColor), Color.blue(_pinnedHeaderTextColor))); + } + else { + header.setBackgroundColor(_pinnedHeaderBackgroundColor); + header.setTextColor(_pinnedHeaderTextColor); + header.setAlpha(alpha / 255.0f); + } + } + +} diff --git a/library/src/main/java/lb/library/cursor/SearchablePinnedHeaderCursorListViewAdapter.java b/library/src/main/java/lb/library/cursor/SearchablePinnedHeaderCursorListViewAdapter.java new file mode 100644 index 0000000..e4d5aa0 --- /dev/null +++ b/library/src/main/java/lb/library/cursor/SearchablePinnedHeaderCursorListViewAdapter.java @@ -0,0 +1,34 @@ +package lb.library.cursor; + +import android.content.Context; +import android.database.Cursor; +import android.widget.AlphabetIndexer; +import android.widget.FilterQueryProvider; +import android.widget.SectionIndexer; + +public abstract class SearchablePinnedHeaderCursorListViewAdapter extends IndexedPinnedHeaderCursorListViewAdapter { + + public SearchablePinnedHeaderCursorListViewAdapter(Context context, Cursor c, boolean autoRequery) { + super(context, c, autoRequery); + + setFilterQueryProvider(new FilterQueryProvider() { + @Override + public Cursor runQuery(CharSequence constraint) { + + return getFilterCursor(constraint); + } + }); + } + + @Override + public void changeCursor(Cursor cursor) { + super.changeCursor(cursor); + SectionIndexer indexer = getSectionIndexer(); + if (indexer instanceof AlphabetIndexer) { + ((AlphabetIndexer) indexer).setCursor(cursor); + } + } + + protected abstract Cursor getFilterCursor(CharSequence constraint); + +}