Java tutorial
/* * Copyright 2013 Tim Roes * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.luciocossio.android.enhancedlistdemo; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.content.SharedPreferences; import android.os.Bundle; import android.support.v4.app.DialogFragment; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarActivity; import android.view.Gravity; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.TextView; import android.widget.Toast; import com.luciocossio.android.enhancedlist.EnhancedList; import com.luciocossio.android.enhancedlist.EnhancedListView; import com.luciocossio.android.enhancedlist.SwipeDirection; import com.luciocossio.android.enhancedlist.UndoStyle; import com.luciocossio.android.enhancedlist.Undoable; import java.util.ArrayList; import java.util.List; public class MainActivity extends ActionBarActivity { private enum ControlGroup { SWIPE_TO_DISMISS } private static final String PREF_UNDO_STYLE = "UNDO_STYLE"; private static final String PREF_SWIPE_TO_DISMISS = "SWIPE_TO_DISMISS"; private static final String PREF_SWIPE_DIRECTION = "SWIPE_DIRECTION"; private static final String PREF_SWIPE_LAYOUT = "SWIPE_LAYOUT"; private EnhancedListAdapter mAdapter; private EnhancedListView mListView; private DrawerLayout mDrawerLayout; private Bundle mUndoStylePref; private Bundle mSwipeDirectionPref; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer); mDrawerLayout.setDrawerListener(new DrawerLayout.DrawerListener() { @Override public void onDrawerSlide(View view, float v) { } @Override public void onDrawerOpened(View view) { mListView.discardUndo(); supportInvalidateOptionsMenu(); } @Override public void onDrawerClosed(View view) { supportInvalidateOptionsMenu(); applySettings(); } @Override public void onDrawerStateChanged(int i) { } }); mListView = (EnhancedListView) findViewById(R.id.list); mAdapter = new EnhancedListAdapter(); mAdapter.resetItems(); mListView.setAdapter(mAdapter); CheckBox swipeToDismiss = (CheckBox) findViewById(R.id.pref_swipetodismiss); swipeToDismiss.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { getPreferences(MODE_PRIVATE).edit().putBoolean(PREF_SWIPE_TO_DISMISS, isChecked).commit(); enableControlGroup(ControlGroup.SWIPE_TO_DISMISS, isChecked); } }); swipeToDismiss.setChecked(getPreferences(MODE_PRIVATE).getBoolean(PREF_SWIPE_TO_DISMISS, false)); CheckBox swipeLayout = (CheckBox) findViewById(R.id.pref_swipelayout); swipeLayout.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { getPreferences(MODE_PRIVATE).edit().putBoolean(PREF_SWIPE_LAYOUT, isChecked).commit(); } }); swipeLayout.setChecked(getPreferences(MODE_PRIVATE).getBoolean(PREF_SWIPE_LAYOUT, false)); mUndoStylePref = new Bundle(); mUndoStylePref.putInt(DialogPicker.DIALOG_TITLE, R.string.pref_undo_style_title); mUndoStylePref.putInt(DialogPicker.DIALOG_ITEMS_ID, R.array.undo_style); mUndoStylePref.putString(DialogPicker.DIALOG_PREF_KEY, PREF_UNDO_STYLE); mSwipeDirectionPref = new Bundle(); mSwipeDirectionPref.putInt(DialogPicker.DIALOG_TITLE, R.string.pref_swipe_direction_title); mSwipeDirectionPref.putInt(DialogPicker.DIALOG_ITEMS_ID, R.array.swipe_direction); mSwipeDirectionPref.putString(DialogPicker.DIALOG_PREF_KEY, PREF_SWIPE_DIRECTION); enableControlGroup(ControlGroup.SWIPE_TO_DISMISS, getPreferences(MODE_PRIVATE).getBoolean(PREF_SWIPE_TO_DISMISS, false)); // Set the callback that handles dismisses. mListView.setDismissCallback(new com.luciocossio.android.enhancedlist.OnDismissCallback() { /** * This method will be called when the user swiped a way or deleted it via * {@link com.luciocossio.android.enhancedlist.EnhancedListView#delete(int)}. * * @param listView The {@link EnhancedListView} the item has been deleted from. * @param position The position of the item to delete from your adapter. * @return An {@link com.luciocossio.android.enhancedlist.Undoable}, if you want * to give the user the possibility to undo the deletion. */ @Override public Undoable onDismiss(EnhancedList listView, final int position) { final String item = (String) mAdapter.getItem(position); mAdapter.remove(position); return new Undoable() { @Override public void undo() { mAdapter.insert(position, item); } }; } }); // Show toast message on click and long click on list items. mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(MainActivity.this, "Clicked on item " + mAdapter.getItem(position), Toast.LENGTH_SHORT).show(); } }); mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(MainActivity.this, "Long clicked on item " + mAdapter.getItem(position), Toast.LENGTH_SHORT).show(); return true; } }); mListView.setSwipingLayout(R.id.swiping_layout); applySettings(); } /** * Enables or disables a group of widgets in the settings drawer. * * @param group The Group that should be disabled/enabled. * @param enabled Whether the group should be enabled or not. */ private void enableControlGroup(ControlGroup group, boolean enabled) { switch (group) { case SWIPE_TO_DISMISS: findViewById(R.id.pref_swipedirection).setEnabled(enabled); findViewById(R.id.pref_swipelayout).setEnabled(enabled); break; } } /** * Applies the settings the user has made to the list view. */ private void applySettings() { SharedPreferences prefs = getPreferences(MODE_PRIVATE); // Set the UndoStyle, the user selected. UndoStyle style; switch (prefs.getInt(PREF_UNDO_STYLE, 0)) { default: style = UndoStyle.SINGLE_POPUP; break; case 1: style = UndoStyle.MULTILEVEL_POPUP; break; case 2: style = UndoStyle.COLLAPSED_POPUP; break; } mListView.setUndoStyle(style); // Enable or disable Swipe to Dismiss if (prefs.getBoolean(PREF_SWIPE_TO_DISMISS, false)) { mListView.enableSwipeToDismiss(); // Set the swipe direction SwipeDirection direction; switch (prefs.getInt(PREF_SWIPE_DIRECTION, 0)) { default: direction = SwipeDirection.BOTH; break; case 1: direction = SwipeDirection.START; break; case 2: direction = SwipeDirection.END; break; } mListView.setSwipeDirection(direction); // Enable or disable swiping layout feature mListView.setSwipingLayout(prefs.getBoolean(PREF_SWIPE_LAYOUT, false) ? R.id.swiping_layout : 0); } else { mListView.disableSwipeToDismiss(); } } @Override protected void onStop() { if (mListView != null) { mListView.discardUndo(); } super.onStop(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onPrepareOptionsMenu(Menu menu) { boolean drawer = mDrawerLayout.isDrawerVisible(Gravity.RIGHT); menu.findItem(R.id.action_settings).setVisible(!drawer); menu.findItem(R.id.action_done).setVisible(drawer); return super.onPrepareOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_settings: mDrawerLayout.openDrawer(Gravity.RIGHT); return true; case R.id.action_done: mDrawerLayout.closeDrawers(); return true; } return super.onOptionsItemSelected(item); } public void resetItems(View view) { mListView.discardUndo(); mAdapter.resetItems(); mDrawerLayout.closeDrawers(); } public void selectUndoStyle(View view) { DialogPicker picker = new DialogPicker(); picker.setArguments(mUndoStylePref); picker.show(getSupportFragmentManager(), "UNDO_STYLE_PICKER"); } public void selectSwipeDirection(View view) { DialogPicker picker = new DialogPicker(); picker.setArguments(mSwipeDirectionPref); picker.show(getSupportFragmentManager(), "SWIPE_DIR_PICKER"); } private class EnhancedListAdapter extends BaseAdapter { private List<String> mItems = new ArrayList<String>(); void resetItems() { mItems.clear(); for (int i = 1; i <= 40; i++) { mItems.add("Item " + i); } notifyDataSetChanged(); } public void remove(int position) { mItems.remove(position); notifyDataSetChanged(); } public void insert(int position, String item) { mItems.add(position, item); notifyDataSetChanged(); } /** * How many items are in the data set represented by this Adapter. * * @return Count of items. */ @Override public int getCount() { return mItems.size(); } /** * Get the data item associated with the specified position in the data set. * * @param position Position of the item whose data we want within the adapter's * data set. * @return The data at the specified position. */ @Override public Object getItem(int position) { return mItems.get(position); } /** * Get the row id associated with the specified position in the list. * * @param position The position of the item within the adapter's data set whose row id we want. * @return The id of the item at the specified position. */ @Override public long getItemId(int position) { return position; } /** * Get a View that displays the data at the specified position in the data set. You can either * create a View manually or inflate it from an XML layout file. When the View is inflated, the * parent View (GridView, ListView...) will apply default layout parameters unless you use * {@link android.view.LayoutInflater#inflate(int, android.view.ViewGroup, boolean)} * to specify a root view and to prevent attachment to the root. * * @param position The position of the item within the adapter's data set of the item whose view * we want. * @param convertView The old view to reuse, if possible. Note: You should check that this view * is non-null and of an appropriate type before using. If it is not possible to convert * this view to display the correct data, this method can create a new view. * Heterogeneous lists can specify their number of view types, so that this View is * always of the right type (see {@link #getViewTypeCount()} and * {@link #getItemViewType(int)}). * @param parent The parent that this view will eventually be attached to * @return A View corresponding to the data at the specified position. */ @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = getLayoutInflater().inflate(R.layout.list_item, parent, false); // Clicking the delete icon, will read the position of the item stored in // the tag and delete it from the list. So we don't need to generate a new // onClickListener every time the content of this view changes. final View origView = convertView; convertView.findViewById(R.id.action_delete).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mListView.delete(((ViewHolder) origView.getTag()).position); } }); holder = new ViewHolder(); assert convertView != null; holder.mTextView = (TextView) convertView.findViewById(R.id.text); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.position = position; holder.mTextView.setText(mItems.get(position)); return convertView; } private class ViewHolder { TextView mTextView; int position; } } private class DialogPicker extends DialogFragment { final static String DIALOG_TITLE = "dialog_title"; final static String DIALOG_ITEMS_ID = "items_id"; final static String DIALOG_PREF_KEY = "pref_key"; @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Bundle args = getArguments(); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(args.getInt(DIALOG_TITLE)); builder.setSingleChoiceItems(args.getInt(DIALOG_ITEMS_ID), getPreferences(MODE_PRIVATE).getInt(args.getString(DIALOG_PREF_KEY), 0), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { SharedPreferences prefs = getPreferences(MODE_PRIVATE); prefs.edit().putInt(args.getString(DIALOG_PREF_KEY), which).commit(); dialog.dismiss(); } }); return builder.create(); } } }