aboutsummaryrefslogtreecommitdiffstats
path: root/OpenPGP-Keychain/src
diff options
context:
space:
mode:
Diffstat (limited to 'OpenPGP-Keychain/src')
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java93
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java80
-rw-r--r--OpenPGP-Keychain/src/se/emilsjolander/stickylistheaders/views/UnderlineTextView.java50
3 files changed, 193 insertions, 30 deletions
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java
index 3dafc84ca..8167ff439 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java
@@ -24,6 +24,9 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
import org.sufficientlysecure.keychain.ui.adapter.KeyListPublicAdapter;
+import se.emilsjolander.stickylistheaders.ApiLevelTooLowException;
+import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
+import android.annotation.SuppressLint;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
@@ -31,58 +34,84 @@ import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
+import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import com.actionbarsherlock.app.SherlockListFragment;
-
-public class KeyListPublicFragment extends SherlockListFragment implements
- LoaderManager.LoaderCallbacks<Cursor> {
+import com.actionbarsherlock.app.SherlockFragment;
+
+/**
+ * Public key list with sticky list headers.
+ *
+ * - uses StickyListHeaders library
+ * - custom adapter: KeyListPublicAdapter
+ *
+ * TODO:
+ * - fix loader with spinning animation
+ * - fix design
+ * - fix view holder in adapter
+ *
+ */
+public class KeyListPublicFragment extends SherlockFragment implements
+ AdapterView.OnItemClickListener, LoaderManager.LoaderCallbacks<Cursor> {
private KeyListPublicActivity mKeyListPublicActivity;
private KeyListPublicAdapter mAdapter;
+ StickyListHeadersListView stickyList;
+
/**
* Define Adapter and Loader on create of Activity
*/
+ @SuppressLint("NewApi")
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mKeyListPublicActivity = (KeyListPublicActivity) getActivity();
- getListView().setOnItemClickListener(new OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
- // start key view on click
- Intent detailsIntent = new Intent(mKeyListPublicActivity, KeyViewActivity.class);
- detailsIntent.setData(KeychainContract.KeyRings.buildPublicKeyRingsUri(Long
- .toString(id)));
- startActivity(detailsIntent);
- }
- });
+ stickyList = (StickyListHeadersListView) getActivity().findViewById(
+ R.id.key_list_public_fragment_stickylist);
+
+ stickyList.setOnItemClickListener(this);
+ // stickyList.setOnHeaderClickListener(this);
+ // stickyList.setOnStickyHeaderOffsetChangedListener(this);
+ // mStickyList.addHeaderView(inflater.inflate(R.layout.list_header, null));
+ // mStickyList.addFooterView(inflater.inflate(R.layout.list_footer, null));
+ // stickyList.setEmptyView(findViewById(R.id.empty));
+ stickyList.setAreHeadersSticky(true);
+ stickyList.setDrawingListUnderStickyHeader(true);
+ stickyList.setFastScrollEnabled(true);
+ try {
+ stickyList.setFastScrollAlwaysVisible(true);
+ } catch (ApiLevelTooLowException e) {
+ }
// Give some text to display if there is no data. In a real
// application this would come from a resource.
- setEmptyText(getString(R.string.list_empty));
-
- // We have a menu item to show in action bar.
- setHasOptionsMenu(true);
+ // setEmptyText(getString(R.string.list_empty));
// Start out with a progress indicator.
- setListShown(false);
+ // setListShown(false);
// Create an empty adapter we will use to display the loaded data.
- mAdapter = new KeyListPublicAdapter(mKeyListPublicActivity, null, Id.type.public_key);
- setListAdapter(mAdapter);
+ // mAdapter = new KeyListPublicAdapter(mKeyListPublicActivity, null, Id.type.public_key);
+ // setListAdapter(mAdapter);
+ // stickyList.setAdapter(mAdapter);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
}
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.key_list_public_fragment, container, false);
+ return view;
+ }
+
// These are the rows that we will retrieve.
static final String[] PROJECTION = new String[] { KeyRings._ID, KeyRings.MASTER_KEY_ID,
UserIds.USER_ID };
@@ -104,13 +133,19 @@ public class KeyListPublicFragment extends SherlockListFragment implements
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
- mAdapter.swapCursor(data);
+ // mAdapter.swapCursor(data);
+ int userIdIndex = data.getColumnIndex(UserIds.USER_ID);
+
+ mAdapter = new KeyListPublicAdapter(mKeyListPublicActivity, data, Id.type.public_key,
+ userIdIndex);
+
+ stickyList.setAdapter(mAdapter);
// The list should now be shown.
if (isResumed()) {
- setListShown(true);
+ // setListShown(true);
} else {
- setListShownNoAnimation(true);
+ // setListShownNoAnimation(true);
}
}
@@ -122,4 +157,12 @@ public class KeyListPublicFragment extends SherlockListFragment implements
mAdapter.swapCursor(null);
}
+ @Override
+ public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
+ // start key view on click
+ Intent detailsIntent = new Intent(mKeyListPublicActivity, KeyViewActivity.class);
+ detailsIntent.setData(KeychainContract.KeyRings.buildPublicKeyRingsUri(Long.toString(id)));
+ startActivity(detailsIntent);
+ }
+
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java
index d72c9d42a..86a47d4d7 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java
@@ -17,30 +17,40 @@
package org.sufficientlysecure.keychain.ui.adapter;
+import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
-import org.sufficientlysecure.keychain.util.SectionCursorAdapter;
+import org.sufficientlysecure.keychain.util.Log;
+import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
import android.content.Context;
import android.database.Cursor;
+import android.support.v4.widget.CursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
-public class KeyListPublicAdapter extends SectionCursorAdapter {
-
+/**
+ * - implements StickyListHeadersAdapter from library - uses view holder pattern for performance
+ *
+ */
+public class KeyListPublicAdapter extends CursorAdapter implements StickyListHeadersAdapter {
private LayoutInflater mInflater;
- public KeyListPublicAdapter(Context context, Cursor c, int flags) {
- super(context, c, android.R.layout.preference_category, 2); // TODO: 2 is user id
+ int mSectionColumnIndex;
+
+ public KeyListPublicAdapter(Context context, Cursor c, int flags, int sectionColumnIndex) {
+ super(context, c, flags);
mInflater = LayoutInflater.from(context);
+ mSectionColumnIndex = sectionColumnIndex;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
+ // TODO: view holder pattern?
int userIdIndex = cursor.getColumnIndex(UserIds.USER_ID);
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
@@ -74,4 +84,64 @@ public class KeyListPublicAdapter extends SectionCursorAdapter {
return mInflater.inflate(R.layout.key_list_group_item, null);
}
+ @Override
+ public View getHeaderView(int position, View convertView, ViewGroup parent) {
+
+ HeaderViewHolder holder;
+ if (convertView == null) {
+ holder = new HeaderViewHolder();
+ convertView = mInflater.inflate(R.layout.stickylist_header, parent, false);
+ holder.text = (TextView) convertView.findViewById(R.id.stickylist_header_text);
+ convertView.setTag(holder);
+ } else {
+ holder = (HeaderViewHolder) convertView.getTag();
+ }
+
+ if (!mDataValid) {
+ // no data available at this point
+ Log.d(Constants.TAG, "getHeaderView: No data available at this point!");
+ return convertView;
+ }
+
+ // similar to getView in CursorAdapter
+ if (!mCursor.moveToPosition(position)) {
+ throw new IllegalStateException("couldn't move cursor to position " + position);
+ }
+
+ // set header text as first char in name
+ String headerText = "" + mCursor.getString(mSectionColumnIndex).subSequence(0, 1).charAt(0);
+ holder.text.setText(headerText);
+ return convertView;
+ }
+
+ /**
+ * Remember that these have to be static, position=1 should always return the same Id that is.
+ */
+ @Override
+ public long getHeaderId(int position) {
+ if (!mDataValid) {
+ // no data available at this point
+ Log.d(Constants.TAG, "getHeaderView: No data available at this point!");
+ return -1;
+ }
+
+ // similar to getView in CursorAdapter
+ if (!mCursor.moveToPosition(position)) {
+ throw new IllegalStateException("couldn't move cursor to position " + position);
+ }
+
+ // return the first character of the name as ID because this is what
+ // headers are based upon
+ return mCursor.getString(mSectionColumnIndex).subSequence(0, 1).charAt(0);
+ }
+
+ class HeaderViewHolder {
+ TextView text;
+ }
+
+ class ViewHolder {
+ TextView mainUserId;
+ TextView mainUserIdRest;
+ }
+
}
diff --git a/OpenPGP-Keychain/src/se/emilsjolander/stickylistheaders/views/UnderlineTextView.java b/OpenPGP-Keychain/src/se/emilsjolander/stickylistheaders/views/UnderlineTextView.java
new file mode 100644
index 000000000..c202c00b8
--- /dev/null
+++ b/OpenPGP-Keychain/src/se/emilsjolander/stickylistheaders/views/UnderlineTextView.java
@@ -0,0 +1,50 @@
+package se.emilsjolander.stickylistheaders.views;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.widget.TextView;
+
+/**
+ * @author Eric Frohnhoefer
+ */
+public class UnderlineTextView extends TextView {
+ private final Paint mPaint = new Paint();
+ private int mUnderlineHeight = 0;
+
+ public UnderlineTextView(Context context) {
+ this(context, null);
+ }
+
+ public UnderlineTextView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public UnderlineTextView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ init(context, attrs);
+ }
+
+ private void init(Context context, AttributeSet attrs) {
+ Resources r = getResources();
+ mUnderlineHeight = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, r.getDisplayMetrics());
+ }
+
+ @Override
+ public void setPadding(int left, int top, int right, int bottom) {
+ super.setPadding(left, top, right, bottom + mUnderlineHeight);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ // Draw the underline the same color as the text
+ mPaint.setColor(getTextColors().getDefaultColor());
+ canvas.drawRect(0, getHeight() - mUnderlineHeight, getWidth(), getHeight(), mPaint);
+ }
+}