diff --git a/app/build.gradle b/app/build.gradle index 6aa4143..470f33a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -42,6 +42,7 @@ dependencies { compile 'com.android.support:support-annotations:21.0.3' compile 'com.android.support:support-v4:21.0.3' compile 'com.android.support:appcompat-v7:21.0.3' + compile 'com.android.support:recyclerview-v7:21.0.3' // Remote dependencies compile 'net.i2p.android:client:0.4@aar' @@ -65,6 +66,7 @@ dependencyVerification { 'com.android.support:support-annotations:fdee2354787ef66b268e75958de3f7f6c4f8f325510a6dac9f49c929f83a63de', 'com.android.support:support-v4:703572d3015a088cc5604b7e38885af3d307c829d0c5ceaf8654ff41c71cd160', 'com.android.support:appcompat-v7:5dbeb5316d0a6027d646ae552804c3baa5e3bd53f7f33db50904d51505c8a0e5', + 'com.android.support:recyclerview-v7:e525ad3f33c84bb12b73d2dc975b55364a53f0f2d0697e043efba59ba73e22d2', 'net.i2p.android:client:9176b5e32f74929856eeedf1dbe7e9f0a64fbb8a58a62b13f929c362353773d3', 'net.i2p.android.ext:floatingactionbutton:ea904b3f290498d6184c5b9affa87949ed5dfe76c5b6a0a307f62313ec094249', 'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f', diff --git a/app/src/main/java/i2p/bote/android/EmailListActivity.java b/app/src/main/java/i2p/bote/android/EmailListActivity.java index e298095..a9afa97 100644 --- a/app/src/main/java/i2p/bote/android/EmailListActivity.java +++ b/app/src/main/java/i2p/bote/android/EmailListActivity.java @@ -18,14 +18,14 @@ import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBarDrawerToggle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.util.DisplayMetrics; import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.widget.AdapterView; import android.widget.ImageView; -import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; @@ -46,6 +46,7 @@ import i2p.bote.folder.FolderListener; import i2p.bote.network.NetworkStatusListener; public class EmailListActivity extends ActionBarActivity implements + FolderListAdapter.OnFolderSelectedListener, EmailListFragment.OnEmailSelectedListener, MoveToDialogFragment.MoveToDialogListener, PasswordCacheListener, @@ -62,8 +63,7 @@ public class EmailListActivity extends ActionBarActivity implements private DrawerLayout mDrawerLayout; private RelativeLayout mDrawerOuter; private FolderListAdapter mFolderAdapter; - private ListView mFolderList; - private int mCurPos; + private String mCurFolder; private ImageView mNetworkStatusIcon; private TextView mNetworkStatusText; private ActionBarDrawerToggle mDrawerToggle; @@ -94,8 +94,7 @@ public class EmailListActivity extends ActionBarActivity implements mSharedPrefs = getSharedPreferences(SHARED_PREFS, 0); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); mDrawerOuter = (RelativeLayout) findViewById(R.id.drawer_outer); - mFolderAdapter = new FolderListAdapter(this); - mFolderList = (ListView) findViewById(R.id.drawer); + RecyclerView mFolderList = (RecyclerView) findViewById(R.id.drawer); mNetworkStatusIcon = (ImageView) findViewById(R.id.network_status_icon); mNetworkStatusText = (TextView) findViewById(R.id.network_status_text); @@ -109,16 +108,21 @@ public class EmailListActivity extends ActionBarActivity implements DrawerLayout.LayoutParams lp = (DrawerLayout.LayoutParams) mDrawerOuter.getLayoutParams(); lp.width = Math.min(dm.widthPixels - toolbar.getLayoutParams().height, maxWidth); - // Set the list of folders - // TODO: This is slow, needs a loader - mFolderAdapter.setData(I2PBote.getInstance().getEmailFolders(), this); - // Set a custom shadow that overlays the main content when the drawer opens mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); + + // use a linear layout manager + RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this); + mFolderList.setLayoutManager(mLayoutManager); + + mFolderAdapter = new FolderListAdapter(this, this); + + // Set the list of folders + // TODO: This is slow, needs a loader + mFolderAdapter.setFolders(I2PBote.getInstance().getEmailFolders(), this); + // Set the adapter for the list view mFolderList.setAdapter(mFolderAdapter); - // Set the list's click listener - mFolderList.setOnItemClickListener(new DrawerItemClickListener()); // Set up drawer toggle mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, @@ -157,10 +161,10 @@ public class EmailListActivity extends ActionBarActivity implements EmailListFragment f = EmailListFragment.newInstance("inbox"); getSupportFragmentManager().beginTransaction() .add(R.id.list_fragment, f).commit(); - mFolderList.setItemChecked(0, true); - mCurPos = 0; + //mFolderList.setItemChecked(0, true); + mCurFolder = ""; } else { - mCurPos = savedInstanceState.getInt(ACTIVE_FOLDER); + mCurFolder = savedInstanceState.getString(ACTIVE_FOLDER); } // Set up fixed actions @@ -215,33 +219,10 @@ public class EmailListActivity extends ActionBarActivity implements } } - private class DrawerItemClickListener implements ListView.OnItemClickListener { - public void onItemClick(AdapterView parent, View view, int pos, long id) { - selectItem(pos); - } - } - - private void selectItem(int position) { - if (position != mCurPos) { - // Create the new fragment - EmailFolder folder = mFolderAdapter.getItem(position); - EmailListFragment f = EmailListFragment.newInstance(folder.getName()); - - // Insert the fragment - getSupportFragmentManager().beginTransaction() - .replace(R.id.list_fragment, f).commit(); - - // Save the current position - mCurPos = position; - } - // Close the drawer - mDrawerLayout.closeDrawer(mDrawerOuter); - } - @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - outState.putInt(ACTIVE_FOLDER, mCurPos); + outState.putString(ACTIVE_FOLDER, mCurFolder); } @Override @@ -378,6 +359,24 @@ public class EmailListActivity extends ActionBarActivity implements mDrawerToggle.onConfigurationChanged(newConfig); } + // FolderListAdapter.OnFolderSelectedListener + + public void onDrawerFolderSelected(EmailFolder folder) { + if (!folder.getName().equals(mCurFolder)) { + // Create the new fragment + EmailListFragment f = EmailListFragment.newInstance(folder.getName()); + + // Insert the fragment + getSupportFragmentManager().beginTransaction() + .replace(R.id.list_fragment, f).commit(); + + // Save the current position + mCurFolder = folder.getName(); + } + // Close the drawer + mDrawerLayout.closeDrawer(mDrawerOuter); + } + // FolderFragment.OnEmailSelectedListener @Override diff --git a/app/src/main/java/i2p/bote/android/FolderListAdapter.java b/app/src/main/java/i2p/bote/android/FolderListAdapter.java index df6aea3..7425980 100644 --- a/app/src/main/java/i2p/bote/android/FolderListAdapter.java +++ b/app/src/main/java/i2p/bote/android/FolderListAdapter.java @@ -1,71 +1,98 @@ package i2p.bote.android; +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + import java.util.List; import i2p.bote.android.util.BoteHelper; import i2p.bote.fileencryption.PasswordException; import i2p.bote.folder.EmailFolder; import i2p.bote.folder.FolderListener; -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ImageView; -import android.widget.TextView; -public class FolderListAdapter extends ArrayAdapter { - private final LayoutInflater mInflater; +public class FolderListAdapter extends RecyclerView.Adapter { + private Context mCtx; + private List mFolders; + private OnFolderSelectedListener mListener; - public FolderListAdapter(Context context) { - super(context, android.R.layout.simple_list_item_2); - mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + // Provide a reference to the views for each data item + // Complex data items may need more than one view per item, and + // you provide access to all the views for a data item in a view holder + public static class ViewHolder extends RecyclerView.ViewHolder { + public ImageView mIcon; + public TextView mName; + + public ViewHolder(View v) { + super(v); + mIcon = (ImageView) v.findViewById(R.id.folder_icon); + mName = (TextView) v.findViewById(R.id.folder_name); + } } - public void setData(List folders, FolderListener folderListener) { + public static interface OnFolderSelectedListener { + public void onDrawerFolderSelected(EmailFolder folder); + } + + public FolderListAdapter(Context ctx, OnFolderSelectedListener listener) { + mCtx = ctx; + mListener = listener; + } + + public void setFolders(List folders, FolderListener folderListener) { // Remove previous FolderListeners - for (int i = 0; i < getCount(); i++) { - getItem(i).removeFolderListener(folderListener); - } - clear(); - if (folders != null) { - for (EmailFolder folder : folders) { - add(folder); - folder.addFolderListener(folderListener); + if (mFolders != null) { + for (EmailFolder folder : mFolders) { + folder.removeFolderListener(folderListener); } } - } - private static class ViewHolder { - ImageView icon; - TextView name; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - ViewHolder holder; - View view; - - if (convertView == null) { - holder = new ViewHolder(); - view = mInflater.inflate(R.layout.listitem_folder_with_icon, parent, false); - holder.icon = (ImageView) view.findViewById(R.id.folder_icon); - holder.name = (TextView) view.findViewById(R.id.folder_name); - view.setTag(holder); - } else { - view = convertView; - holder = (ViewHolder) view.getTag(); + mFolders = folders; + for (EmailFolder folder : folders) { + folder.addFolderListener(folderListener); } - EmailFolder folder = getItem(position); + notifyDataSetChanged(); + } - holder.icon.setImageDrawable(BoteHelper.getFolderIcon(getContext(), folder)); + // Create new views (invoked by the layout manager) + @Override + public FolderListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, + int viewType) { + View v = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.listitem_folder_with_icon, parent, false); + return new ViewHolder(v); + } + + // Replace the contents of a view (invoked by the layout manager) + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + final EmailFolder folder = mFolders.get(position); + + holder.mIcon.setImageDrawable(BoteHelper.getFolderIcon(mCtx, folder)); try { - holder.name.setText(BoteHelper.getFolderDisplayNameWithNew(getContext(), folder)); + holder.mName.setText(BoteHelper.getFolderDisplayNameWithNew(mCtx, folder)); } catch (PasswordException e) { // Password fetching is handled in EmailListFragment - holder.name.setText(BoteHelper.getFolderDisplayName(getContext(), folder)); + holder.mName.setText(BoteHelper.getFolderDisplayName(mCtx, folder)); } - return view; + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + mListener.onDrawerFolderSelected(folder); + } + }); + } + + // Return the size of the dataset (invoked by the layout manager) + @Override + public int getItemCount() { + if (mFolders != null) + return mFolders.size(); + return 0; } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 5c6dd20..adba5c8 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -36,10 +36,10 @@ android:layout_gravity="start" android:background="@color/background_floating_material_light"> -