mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 17:18:52 -06:00
Create HabitListView and move most code from Fragment to it
This commit is contained in:
@@ -50,7 +50,7 @@ import org.isoron.uhabits.widgets.WidgetManager;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public class MainActivity extends BaseActivity
|
public class MainActivity extends BaseActivity
|
||||||
implements ListHabitsFragment.OnHabitClickListener, MainController.Screen
|
implements ListHabitsFragment.Listener, MainController.Screen
|
||||||
{
|
{
|
||||||
private MainController controller;
|
private MainController controller;
|
||||||
private ListHabitsFragment listHabitsFragment;
|
private ListHabitsFragment listHabitsFragment;
|
||||||
@@ -88,7 +88,7 @@ public class MainActivity extends BaseActivity
|
|||||||
public boolean onCreateOptionsMenu(Menu menu)
|
public boolean onCreateOptionsMenu(Menu menu)
|
||||||
{
|
{
|
||||||
menu.clear();
|
menu.clear();
|
||||||
getMenuInflater().inflate(R.menu.list_habits_menu, menu);
|
getMenuInflater().inflate(R.menu.main_activity, menu);
|
||||||
MenuItem nightModeItem = menu.findItem(R.id.action_night_mode);
|
MenuItem nightModeItem = menu.findItem(R.id.action_night_mode);
|
||||||
nightModeItem.setChecked(InterfaceUtils.isNightMode());
|
nightModeItem.setChecked(InterfaceUtils.isNightMode());
|
||||||
return true;
|
return true;
|
||||||
@@ -191,7 +191,7 @@ public class MainActivity extends BaseActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onHabitClicked(Habit habit)
|
public void onHabitClick(Habit habit)
|
||||||
{
|
{
|
||||||
showHabitScreen(habit);
|
showHabitScreen(habit);
|
||||||
}
|
}
|
||||||
@@ -258,12 +258,12 @@ public class MainActivity extends BaseActivity
|
|||||||
@Override
|
@Override
|
||||||
public void refresh(Long refreshKey)
|
public void refresh(Long refreshKey)
|
||||||
{
|
{
|
||||||
listHabitsFragment.loader.updateAllHabits(true);
|
listHabitsFragment.refresh(refreshKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProgressBar getProgressBar()
|
public ProgressBar getProgressBar()
|
||||||
{
|
{
|
||||||
return new AndroidProgressBar(listHabitsFragment.progressBar);
|
return new AndroidProgressBar(listHabitsFragment.getProgressBar());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,16 +31,16 @@ import org.isoron.uhabits.models.Habit;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
class ListHabitsAdapter extends BaseAdapter
|
class HabitListAdapter extends BaseAdapter
|
||||||
{
|
{
|
||||||
private LayoutInflater inflater;
|
private LayoutInflater inflater;
|
||||||
private ListHabitsLoader loader;
|
private HabitListLoader loader;
|
||||||
private ListHabitsHelper helper;
|
private ListHabitsHelper helper;
|
||||||
private List selectedPositions;
|
private List selectedPositions;
|
||||||
private View.OnLongClickListener onCheckmarkLongClickListener;
|
private View.OnLongClickListener onCheckmarkLongClickListener;
|
||||||
private View.OnClickListener onCheckmarkClickListener;
|
private View.OnClickListener onCheckmarkClickListener;
|
||||||
|
|
||||||
public ListHabitsAdapter(Context context, ListHabitsLoader loader)
|
public HabitListAdapter(Context context, HabitListLoader loader)
|
||||||
{
|
{
|
||||||
this.loader = loader;
|
this.loader = loader;
|
||||||
|
|
||||||
@@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.ui.habits.list;
|
package org.isoron.uhabits.ui.habits.list;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
import org.isoron.uhabits.utils.DateUtils;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
import org.isoron.uhabits.tasks.BaseTask;
|
import org.isoron.uhabits.tasks.BaseTask;
|
||||||
@@ -26,7 +28,7 @@ import org.isoron.uhabits.tasks.BaseTask;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ListHabitsLoader
|
public class HabitListLoader
|
||||||
{
|
{
|
||||||
public interface Listener
|
public interface Listener
|
||||||
{
|
{
|
||||||
@@ -36,6 +38,7 @@ public class ListHabitsLoader
|
|||||||
private BaseTask currentFetchTask;
|
private BaseTask currentFetchTask;
|
||||||
private int checkmarkCount;
|
private int checkmarkCount;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private Listener listener;
|
private Listener listener;
|
||||||
private Long lastLoadTimestamp;
|
private Long lastLoadTimestamp;
|
||||||
|
|
||||||
@@ -56,7 +59,7 @@ public class ListHabitsLoader
|
|||||||
this.checkmarkCount = checkmarkCount;
|
this.checkmarkCount = checkmarkCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setListener(Listener listener)
|
public void setListener(@Nullable Listener listener)
|
||||||
{
|
{
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
}
|
}
|
||||||
@@ -66,7 +69,7 @@ public class ListHabitsLoader
|
|||||||
return lastLoadTimestamp;
|
return lastLoadTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListHabitsLoader()
|
public HabitListLoader()
|
||||||
{
|
{
|
||||||
habits = new HashMap<>();
|
habits = new HashMap<>();
|
||||||
checkmarks = new HashMap<>();
|
checkmarks = new HashMap<>();
|
||||||
@@ -164,7 +167,6 @@ public class ListHabitsLoader
|
|||||||
currentFetchTask = null;
|
currentFetchTask = null;
|
||||||
|
|
||||||
if(listener != null) listener.onLoadFinished();
|
if(listener != null) listener.onLoadFinished();
|
||||||
|
|
||||||
super.onPostExecute(null);
|
super.onPostExecute(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,9 +196,7 @@ public class ListHabitsLoader
|
|||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Void aVoid)
|
protected void onPostExecute(Void aVoid)
|
||||||
{
|
{
|
||||||
if(listener != null)
|
if(listener != null) listener.onLoadFinished();
|
||||||
listener.onLoadFinished();
|
|
||||||
|
|
||||||
super.onPostExecute(null);
|
super.onPostExecute(null);
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
@@ -42,9 +42,9 @@ import org.isoron.uhabits.utils.InterfaceUtils;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class HabitSelectionCallback implements ActionMode.Callback
|
public class HabitListSelectionCallback implements ActionMode.Callback
|
||||||
{
|
{
|
||||||
private ListHabitsLoader loader;
|
private HabitListLoader loader;
|
||||||
private List<Integer> selectedPositions;
|
private List<Integer> selectedPositions;
|
||||||
private BaseActivity activity;
|
private BaseActivity activity;
|
||||||
private Listener listener;
|
private Listener listener;
|
||||||
@@ -55,7 +55,7 @@ public class HabitSelectionCallback implements ActionMode.Callback
|
|||||||
void onActionModeDestroyed(ActionMode mode);
|
void onActionModeDestroyed(ActionMode mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HabitSelectionCallback(BaseActivity activity, ListHabitsLoader loader)
|
public HabitListSelectionCallback(BaseActivity activity, HabitListLoader loader)
|
||||||
{
|
{
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
this.loader = loader;
|
this.loader = loader;
|
||||||
@@ -80,7 +80,7 @@ public class HabitSelectionCallback implements ActionMode.Callback
|
|||||||
@Override
|
@Override
|
||||||
public boolean onCreateActionMode(ActionMode mode, Menu menu)
|
public boolean onCreateActionMode(ActionMode mode, Menu menu)
|
||||||
{
|
{
|
||||||
activity.getMenuInflater().inflate(R.menu.list_habits_context, menu);
|
activity.getMenuInflater().inflate(R.menu.list_habits_selection, menu);
|
||||||
updateTitle(mode);
|
updateTitle(mode);
|
||||||
updateActions(menu);
|
updateActions(menu);
|
||||||
return true;
|
return true;
|
||||||
@@ -0,0 +1,273 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of Loop Habit Tracker.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.ui.habits.list;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.HapticFeedbackConstants;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
|
||||||
|
import com.mobeta.android.dslv.DragSortController;
|
||||||
|
import com.mobeta.android.dslv.DragSortListView;
|
||||||
|
|
||||||
|
import org.isoron.uhabits.R;
|
||||||
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
import org.isoron.uhabits.utils.Preferences;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class HabitListView extends DragSortListView implements View.OnClickListener,
|
||||||
|
View.OnLongClickListener, DragSortListView.DropListener, AdapterView.OnItemClickListener,
|
||||||
|
AdapterView.OnItemLongClickListener, DragSortListView.DragListener, HabitListLoader.Listener
|
||||||
|
{
|
||||||
|
private final HabitListLoader loader;
|
||||||
|
private final HabitListAdapter adapter;
|
||||||
|
private final ListHabitsHelper helper;
|
||||||
|
private final Preferences prefs;
|
||||||
|
private final List<Integer> selectedPositions;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Listener listener;
|
||||||
|
private long lastLongClick;
|
||||||
|
private boolean showArchived;
|
||||||
|
|
||||||
|
public HabitListView(Context context, AttributeSet attrs)
|
||||||
|
{
|
||||||
|
super(context, attrs);
|
||||||
|
|
||||||
|
loader = new HabitListLoader();
|
||||||
|
adapter = new HabitListAdapter(context, loader);
|
||||||
|
selectedPositions = new LinkedList<>();
|
||||||
|
prefs = Preferences.getInstance();
|
||||||
|
helper = new ListHabitsHelper(getContext(), loader);
|
||||||
|
|
||||||
|
adapter.setSelectedPositions(selectedPositions);
|
||||||
|
adapter.setOnCheckmarkClickListener(this);
|
||||||
|
adapter.setOnCheckmarkLongClickListener(this);
|
||||||
|
loader.setListener(this);
|
||||||
|
loader.setCheckmarkCount(helper.getButtonCount());
|
||||||
|
|
||||||
|
setAdapter(adapter);
|
||||||
|
setOnItemClickListener(this);
|
||||||
|
setOnItemLongClickListener(this);
|
||||||
|
setDropListener(this);
|
||||||
|
setDragListener(this);
|
||||||
|
setFloatViewManager(new HabitsDragSortController());
|
||||||
|
setDragEnabled(false);
|
||||||
|
setLongClickable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HabitListLoader getLoader()
|
||||||
|
{
|
||||||
|
return loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Integer> getSelectedPositions()
|
||||||
|
{
|
||||||
|
return selectedPositions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setListener(@Nullable Listener l)
|
||||||
|
{
|
||||||
|
this.listener = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drop(int from, int to)
|
||||||
|
{
|
||||||
|
if(from == to) return;
|
||||||
|
cancelSelection();
|
||||||
|
|
||||||
|
loader.reorder(from, to);
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
loader.updateAllHabits(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v)
|
||||||
|
{
|
||||||
|
if (v.getId() != R.id.tvCheck) return;
|
||||||
|
|
||||||
|
if (prefs.isShortToggleEnabled()) toggleCheckmark(v);
|
||||||
|
else if(listener != null) listener.onInvalidToggle();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onLongClick(View v)
|
||||||
|
{
|
||||||
|
lastLongClick = new Date().getTime();
|
||||||
|
if (v.getId() != R.id.tvCheck) return true;
|
||||||
|
if (prefs.isShortToggleEnabled()) return true;
|
||||||
|
toggleCheckmark(v);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggleShowArchived()
|
||||||
|
{
|
||||||
|
showArchived = !showArchived;
|
||||||
|
loader.setIncludeArchived(showArchived);
|
||||||
|
loader.updateAllHabits(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toggleCheckmark(View v)
|
||||||
|
{
|
||||||
|
Long id = helper.getHabitIdFromCheckmarkView(v);
|
||||||
|
Habit habit = loader.habits.get(id);
|
||||||
|
if(habit == null) return;
|
||||||
|
|
||||||
|
float x = v.getX() + v.getWidth() / 2.0f + ((View) v.getParent()).getX();
|
||||||
|
float y = v.getY() + v.getHeight() / 2.0f + ((View) v.getParent()).getY();
|
||||||
|
helper.triggerRipple((View) v.getParent().getParent(), x, y);
|
||||||
|
|
||||||
|
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||||
|
helper.toggleCheckmarkView(v, habit);
|
||||||
|
|
||||||
|
long timestamp = helper.getTimestampFromCheckmarkView(v);
|
||||||
|
|
||||||
|
if(listener != null) listener.onToggleCheckmark(habit, timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
|
||||||
|
{
|
||||||
|
if (new Date().getTime() - lastLongClick < 1000) return;
|
||||||
|
|
||||||
|
if(selectedPositions.isEmpty())
|
||||||
|
{
|
||||||
|
Habit habit = loader.habitsList.get(position);
|
||||||
|
if(listener != null) listener.onHabitClick(habit);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
toggleItemSelected(position);
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toggleItemSelected(int position)
|
||||||
|
{
|
||||||
|
int k = selectedPositions.indexOf(position);
|
||||||
|
if(k < 0) selectedPositions.add(position);
|
||||||
|
else selectedPositions.remove(k);
|
||||||
|
|
||||||
|
if(listener != null)
|
||||||
|
{
|
||||||
|
if (selectedPositions.isEmpty()) listener.onHabitSelectionFinish();
|
||||||
|
else listener.onHabitSelectionChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id)
|
||||||
|
{
|
||||||
|
selectHabit(position);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void selectHabit(int position)
|
||||||
|
{
|
||||||
|
if(!selectedPositions.contains(position)) selectedPositions.add(position);
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
|
||||||
|
if(listener != null)
|
||||||
|
{
|
||||||
|
if (selectedPositions.size() == 1) listener.onHabitSelectionStart();
|
||||||
|
else listener.onHabitSelectionChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drag(int from, int to)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startDrag(int position)
|
||||||
|
{
|
||||||
|
selectHabit(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getShowArchived()
|
||||||
|
{
|
||||||
|
return showArchived;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelSelection()
|
||||||
|
{
|
||||||
|
selectedPositions.clear();
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
setDragEnabled(true);
|
||||||
|
if(listener != null) listener.onHabitSelectionFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refreshData(Long refreshKey)
|
||||||
|
{
|
||||||
|
if (refreshKey == null) loader.updateAllHabits(true);
|
||||||
|
else loader.updateHabit(refreshKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadFinished()
|
||||||
|
{
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
if(listener != null) listener.onDatasetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class HabitsDragSortController extends DragSortController
|
||||||
|
{
|
||||||
|
public HabitsDragSortController()
|
||||||
|
{
|
||||||
|
super(HabitListView.this);
|
||||||
|
setRemoveEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateFloatView(int position)
|
||||||
|
{
|
||||||
|
return adapter.getView(position, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyFloatView(View floatView)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Listener
|
||||||
|
{
|
||||||
|
void onToggleCheckmark(Habit habit, long timestamp);
|
||||||
|
|
||||||
|
void onHabitClick(Habit habit);
|
||||||
|
|
||||||
|
void onHabitSelectionStart();
|
||||||
|
|
||||||
|
void onHabitSelectionFinish();
|
||||||
|
|
||||||
|
void onHabitSelectionChange();
|
||||||
|
|
||||||
|
void onInvalidToggle();
|
||||||
|
|
||||||
|
void onDatasetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,7 +28,6 @@ public class ListHabitsController
|
|||||||
|
|
||||||
private Screen screen;
|
private Screen screen;
|
||||||
|
|
||||||
|
|
||||||
public void setScreen(Screen screen)
|
public void setScreen(Screen screen)
|
||||||
{
|
{
|
||||||
this.screen = screen;
|
this.screen = screen;
|
||||||
|
|||||||
@@ -23,25 +23,17 @@ import android.app.Activity;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v7.view.ActionMode;
|
import android.support.v7.view.ActionMode;
|
||||||
import android.view.HapticFeedbackConstants;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.View.OnLongClickListener;
|
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.AdapterView.OnItemClickListener;
|
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.mobeta.android.dslv.DragSortController;
|
|
||||||
import com.mobeta.android.dslv.DragSortListView;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.utils.Preferences;
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.commands.Command;
|
import org.isoron.uhabits.commands.Command;
|
||||||
import org.isoron.uhabits.commands.ToggleRepetitionCommand;
|
import org.isoron.uhabits.commands.ToggleRepetitionCommand;
|
||||||
@@ -49,40 +41,24 @@ import org.isoron.uhabits.models.Habit;
|
|||||||
import org.isoron.uhabits.ui.BaseActivity;
|
import org.isoron.uhabits.ui.BaseActivity;
|
||||||
import org.isoron.uhabits.ui.HintManager;
|
import org.isoron.uhabits.ui.HintManager;
|
||||||
import org.isoron.uhabits.ui.habits.edit.EditHabitDialogFragment;
|
import org.isoron.uhabits.ui.habits.edit.EditHabitDialogFragment;
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
|
||||||
import org.isoron.uhabits.utils.InterfaceUtils;
|
import org.isoron.uhabits.utils.InterfaceUtils;
|
||||||
import org.isoron.uhabits.utils.InterfaceUtils.OnSavedListener;
|
import org.isoron.uhabits.utils.InterfaceUtils.OnSavedListener;
|
||||||
import org.isoron.uhabits.utils.ReminderUtils;
|
import org.isoron.uhabits.utils.ReminderUtils;
|
||||||
|
|
||||||
import java.util.Date;
|
public class ListHabitsFragment extends Fragment implements OnSavedListener, OnClickListener,
|
||||||
import java.util.LinkedList;
|
HabitListSelectionCallback.Listener, ListHabitsController.Screen
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class ListHabitsFragment extends Fragment
|
|
||||||
implements OnSavedListener, OnItemClickListener, OnLongClickListener,
|
|
||||||
OnClickListener, ListHabitsLoader.Listener, AdapterView.OnItemLongClickListener,
|
|
||||||
HabitSelectionCallback.Listener, ListHabitsController.Screen
|
|
||||||
{
|
{
|
||||||
long lastLongClick = 0;
|
|
||||||
private boolean showArchived;
|
|
||||||
|
|
||||||
private ActionMode actionMode;
|
private ActionMode actionMode;
|
||||||
private ListHabitsAdapter adapter;
|
|
||||||
public ListHabitsLoader loader;
|
|
||||||
private HintManager hintManager;
|
private HintManager hintManager;
|
||||||
private ListHabitsHelper helper;
|
private ListHabitsHelper helper;
|
||||||
private List<Integer> selectedPositions;
|
private Listener habitClickListener;
|
||||||
private OnHabitClickListener habitClickListener;
|
|
||||||
private BaseActivity activity;
|
private BaseActivity activity;
|
||||||
|
|
||||||
private DragSortListView listView;
|
private HabitListView listView;
|
||||||
private LinearLayout llButtonsHeader;
|
private LinearLayout llButtonsHeader;
|
||||||
public ProgressBar progressBar;
|
private ProgressBar progressBar;
|
||||||
private View llEmpty;
|
private View llEmpty;
|
||||||
|
|
||||||
private ListHabitsController controller;
|
|
||||||
private Preferences prefs;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState)
|
Bundle savedInstanceState)
|
||||||
@@ -93,23 +69,16 @@ public class ListHabitsFragment extends Fragment
|
|||||||
llButtonsHeader = (LinearLayout) view.findViewById(R.id.llButtonsHeader);
|
llButtonsHeader = (LinearLayout) view.findViewById(R.id.llButtonsHeader);
|
||||||
llEmpty = view.findViewById(R.id.llEmpty);
|
llEmpty = view.findViewById(R.id.llEmpty);
|
||||||
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
|
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
|
||||||
progressBar.setVisibility(View.GONE);
|
listView = (HabitListView) view.findViewById(R.id.listView);
|
||||||
|
TextView tvStarEmpty = (TextView) view.findViewById(R.id.tvStarEmpty);
|
||||||
selectedPositions = new LinkedList<>();
|
|
||||||
loader = new ListHabitsLoader();
|
|
||||||
helper = new ListHabitsHelper(activity, loader);
|
|
||||||
|
|
||||||
|
helper = new ListHabitsHelper(activity, listView.getLoader());
|
||||||
hintManager = new HintManager(activity, llHint);
|
hintManager = new HintManager(activity, llHint);
|
||||||
|
|
||||||
loader.setListener(this);
|
|
||||||
loader.setCheckmarkCount(helper.getButtonCount());
|
|
||||||
|
|
||||||
llHint.setOnClickListener(this);
|
llHint.setOnClickListener(this);
|
||||||
|
|
||||||
TextView tvStarEmpty = (TextView) view.findViewById(R.id.tvStarEmpty);
|
|
||||||
tvStarEmpty.setTypeface(InterfaceUtils.getFontAwesome(activity));
|
tvStarEmpty.setTypeface(InterfaceUtils.getFontAwesome(activity));
|
||||||
|
listView.setListener(new HabitListViewListener());
|
||||||
createListView(view);
|
setHasOptionsMenu(true);
|
||||||
|
|
||||||
if(savedInstanceState != null)
|
if(savedInstanceState != null)
|
||||||
{
|
{
|
||||||
@@ -118,75 +87,36 @@ public class ListHabitsFragment extends Fragment
|
|||||||
if(frag != null) frag.setOnSavedListener(this);
|
if(frag != null) frag.setOnSavedListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
loader.updateAllHabits(true);
|
|
||||||
|
|
||||||
controller = new ListHabitsController();
|
|
||||||
controller.setScreen(this);
|
|
||||||
prefs = Preferences.getInstance();
|
|
||||||
|
|
||||||
setHasOptionsMenu(true);
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createListView(View view)
|
|
||||||
{
|
|
||||||
listView = (DragSortListView) view.findViewById(R.id.listView);
|
|
||||||
adapter = new ListHabitsAdapter(getActivity(), loader);
|
|
||||||
adapter.setSelectedPositions(selectedPositions);
|
|
||||||
adapter.setOnCheckmarkClickListener(this);
|
|
||||||
adapter.setOnCheckmarkLongClickListener(this);
|
|
||||||
|
|
||||||
DragSortListView.DragListener dragListener = new HabitsDragListener();
|
|
||||||
DragSortController dragSortController = new HabitsDragSortController();
|
|
||||||
|
|
||||||
listView.setAdapter(adapter);
|
|
||||||
listView.setOnItemClickListener(this);
|
|
||||||
listView.setOnItemLongClickListener(this);
|
|
||||||
listView.setDropListener(new HabitsDropListener());
|
|
||||||
listView.setDragListener(dragListener);
|
|
||||||
listView.setFloatViewManager(dragSortController);
|
|
||||||
listView.setDragEnabled(true);
|
|
||||||
listView.setLongClickable(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public void onAttach(Activity activity)
|
public void onAttach(Activity activity)
|
||||||
{
|
{
|
||||||
super.onAttach(activity);
|
super.onAttach(activity);
|
||||||
this.activity = (BaseActivity) activity;
|
this.activity = (BaseActivity) activity;
|
||||||
habitClickListener = (OnHabitClickListener) activity;
|
habitClickListener = (Listener) activity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume()
|
public void onResume()
|
||||||
{
|
{
|
||||||
super.onResume();
|
super.onResume();
|
||||||
Long timestamp = loader.getLastLoadTimestamp();
|
|
||||||
|
|
||||||
if (timestamp != null && timestamp != DateUtils.getStartOfToday())
|
|
||||||
loader.updateAllHabits(true);
|
|
||||||
|
|
||||||
|
listView.refreshData(null);
|
||||||
helper.updateEmptyMessage(llEmpty);
|
helper.updateEmptyMessage(llEmpty);
|
||||||
helper.updateHeader(llButtonsHeader);
|
helper.updateHeader(llButtonsHeader);
|
||||||
hintManager.showHintIfAppropriate();
|
hintManager.showHintIfAppropriate();
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoadFinished()
|
|
||||||
{
|
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
helper.updateEmptyMessage(llEmpty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
|
||||||
{
|
{
|
||||||
super.onCreateOptionsMenu(menu, inflater);
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
inflater.inflate(R.menu.list_habits_options, menu);
|
inflater.inflate(R.menu.list_habits_fragment, menu);
|
||||||
MenuItem showArchivedItem = menu.findItem(R.id.action_show_archived);
|
MenuItem showArchivedItem = menu.findItem(R.id.action_show_archived);
|
||||||
showArchivedItem.setChecked(showArchived);
|
showArchivedItem.setChecked(listView.getShowArchived());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -209,9 +139,7 @@ public class ListHabitsFragment extends Fragment
|
|||||||
|
|
||||||
private void toggleShowArchived()
|
private void toggleShowArchived()
|
||||||
{
|
{
|
||||||
showArchived = !showArchived;
|
listView.toggleShowArchived();
|
||||||
loader.setIncludeArchived(showArchived);
|
|
||||||
loader.updateAllHabits(true);
|
|
||||||
activity.invalidateOptionsMenu();
|
activity.invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,57 +150,28 @@ public class ListHabitsFragment extends Fragment
|
|||||||
frag.show(getFragmentManager(), "editHabit");
|
frag.show(getFragmentManager(), "editHabit");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void startActionMode()
|
||||||
public void onItemClick(AdapterView parent, View view, int position, long id)
|
|
||||||
{
|
{
|
||||||
if (new Date().getTime() - lastLongClick < 1000) return;
|
HabitListSelectionCallback callback =
|
||||||
|
new HabitListSelectionCallback(activity, listView.getLoader());
|
||||||
if(actionMode == null)
|
callback.setSelectedPositions(listView.getSelectedPositions());
|
||||||
{
|
|
||||||
Habit habit = loader.habitsList.get(position);
|
|
||||||
habitClickListener.onHabitClicked(habit);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
toggleItemSelected(position);
|
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void toggleItemSelected(int position)
|
|
||||||
{
|
|
||||||
int k = selectedPositions.indexOf(position);
|
|
||||||
if(k < 0) selectedPositions.add(position);
|
|
||||||
else selectedPositions.remove(k);
|
|
||||||
|
|
||||||
if(selectedPositions.isEmpty()) actionMode.finish();
|
|
||||||
else actionMode.invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id)
|
|
||||||
{
|
|
||||||
selectHabit(position);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void selectHabit(int position)
|
|
||||||
{
|
|
||||||
if(!selectedPositions.contains(position)) selectedPositions.add(position);
|
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
if(actionMode == null) startSupportActionMode();
|
|
||||||
actionMode.invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startSupportActionMode()
|
|
||||||
{
|
|
||||||
HabitSelectionCallback callback = new HabitSelectionCallback(activity, loader);
|
|
||||||
callback.setSelectedPositions(selectedPositions);
|
|
||||||
callback.setOnSavedListener(this);
|
callback.setOnSavedListener(this);
|
||||||
callback.setListener(this);
|
callback.setListener(this);
|
||||||
actionMode = activity.startSupportActionMode(callback);
|
actionMode = activity.startSupportActionMode(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void finishActionMode()
|
||||||
|
{
|
||||||
|
if(actionMode != null) actionMode.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActionModeDestroyed(ActionMode mode)
|
||||||
|
{
|
||||||
|
actionMode = null;
|
||||||
|
listView.cancelSelection();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaved(Command command, Object savedObject)
|
public void onSaved(Command command, Object savedObject)
|
||||||
{
|
{
|
||||||
@@ -280,49 +179,12 @@ public class ListHabitsFragment extends Fragment
|
|||||||
|
|
||||||
if (h == null) activity.executeCommand(command, null);
|
if (h == null) activity.executeCommand(command, null);
|
||||||
else activity.executeCommand(command, h.getId());
|
else activity.executeCommand(command, h.getId());
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
|
listView.refreshData(null);
|
||||||
|
|
||||||
ReminderUtils.createReminderAlarms(activity);
|
ReminderUtils.createReminderAlarms(activity);
|
||||||
|
|
||||||
if(actionMode != null) actionMode.finish();
|
finishActionMode();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onLongClick(View v)
|
|
||||||
{
|
|
||||||
lastLongClick = new Date().getTime();
|
|
||||||
|
|
||||||
switch (v.getId())
|
|
||||||
{
|
|
||||||
case R.id.tvCheck:
|
|
||||||
onCheckmarkLongClick(v);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onCheckmarkLongClick(View v)
|
|
||||||
{
|
|
||||||
if (prefs.isShortToggleEnabled()) return;
|
|
||||||
toggleCheckmark(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void toggleCheckmark(View v)
|
|
||||||
{
|
|
||||||
Long id = helper.getHabitIdFromCheckmarkView(v);
|
|
||||||
Habit habit = loader.habits.get(id);
|
|
||||||
if(habit == null) return;
|
|
||||||
|
|
||||||
float x = v.getX() + v.getWidth() / 2.0f + ((View) v.getParent()).getX();
|
|
||||||
float y = v.getY() + v.getHeight() / 2.0f + ((View) v.getParent()).getY();
|
|
||||||
helper.triggerRipple((View) v.getParent().getParent(), x, y);
|
|
||||||
|
|
||||||
listView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
|
||||||
helper.toggleCheckmarkView(v, habit);
|
|
||||||
|
|
||||||
long timestamp = helper.getTimestampFromCheckmarkView(v);
|
|
||||||
executeCommand(new ToggleRepetitionCommand(habit, timestamp), habit.getId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void executeCommand(Command c, Long refreshKey)
|
private void executeCommand(Command c, Long refreshKey)
|
||||||
@@ -333,84 +195,72 @@ public class ListHabitsFragment extends Fragment
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(View v)
|
public void onClick(View v)
|
||||||
{
|
{
|
||||||
switch (v.getId())
|
if (v.getId() == R.id.llHint)
|
||||||
{
|
hintManager.dismissHint();
|
||||||
case R.id.tvCheck:
|
|
||||||
if (prefs.isShortToggleEnabled()) toggleCheckmark(v);
|
|
||||||
else activity.showMessage(R.string.long_press_to_toggle);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R.id.llHint:
|
|
||||||
hintManager.dismissHint();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onPostExecuteCommand(Long refreshKey)
|
public void onPostExecuteCommand(Long refreshKey)
|
||||||
{
|
{
|
||||||
if (refreshKey == null) loader.updateAllHabits(true);
|
listView.refreshData(refreshKey);
|
||||||
else loader.updateHabit(refreshKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public ProgressBar getProgressBar()
|
||||||
public void onActionModeDestroyed(ActionMode mode)
|
|
||||||
{
|
{
|
||||||
actionMode = null;
|
return progressBar;
|
||||||
selectedPositions.clear();
|
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
listView.setDragEnabled(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OnHabitClickListener
|
public void refresh(Long refreshKey)
|
||||||
{
|
{
|
||||||
void onHabitClicked(Habit habit);
|
listView.refreshData(refreshKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class HabitsDragSortController extends DragSortController
|
public interface Listener
|
||||||
{
|
{
|
||||||
public HabitsDragSortController()
|
void onHabitClick(Habit habit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class HabitListViewListener implements HabitListView.Listener
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onToggleCheckmark(Habit habit, long timestamp)
|
||||||
{
|
{
|
||||||
super(ListHabitsFragment.this.listView);
|
executeCommand(new ToggleRepetitionCommand(habit, timestamp), habit.getId());
|
||||||
setRemoveEnabled(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateFloatView(int position)
|
public void onHabitClick(Habit habit)
|
||||||
{
|
{
|
||||||
return adapter.getView(position, null, null);
|
habitClickListener.onHabitClick(habit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyFloatView(View floatView)
|
public void onHabitSelectionStart()
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class HabitsDropListener implements DragSortListView.DropListener
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void drop(int from, int to)
|
|
||||||
{
|
|
||||||
if(from == to) return;
|
|
||||||
if(actionMode != null) actionMode.finish();
|
|
||||||
|
|
||||||
loader.reorder(from, to);
|
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
loader.updateAllHabits(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class HabitsDragListener implements DragSortListView.DragListener
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void drag(int from, int to)
|
|
||||||
{
|
{
|
||||||
|
if(actionMode == null) startActionMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startDrag(int position)
|
public void onHabitSelectionFinish()
|
||||||
{
|
{
|
||||||
selectHabit(position);
|
finishActionMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHabitSelectionChange()
|
||||||
|
{
|
||||||
|
if(actionMode != null) actionMode.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInvalidToggle()
|
||||||
|
{
|
||||||
|
activity.showMessage(R.string.long_press_to_toggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDatasetChanged()
|
||||||
|
{
|
||||||
|
helper.updateEmptyMessage(llEmpty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,9 +50,9 @@ public class ListHabitsHelper
|
|||||||
private final int mediumContrastColor;
|
private final int mediumContrastColor;
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final ListHabitsLoader loader;
|
private final HabitListLoader loader;
|
||||||
|
|
||||||
public ListHabitsHelper(Context context, ListHabitsLoader loader)
|
public ListHabitsHelper(Context context, HabitListLoader loader)
|
||||||
{
|
{
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.loader = loader;
|
this.loader = loader;
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ public class ShowHabitFragment extends Fragment
|
|||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
|
||||||
{
|
{
|
||||||
inflater.inflate(R.menu.show_habit_fragment_menu, menu);
|
inflater.inflate(R.menu.show_habit_fragment, menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="#ffffff">
|
android:background="#ffffff">
|
||||||
|
|
||||||
<com.mobeta.android.dslv.DragSortListView
|
<org.isoron.uhabits.ui.habits.list.HabitListView
|
||||||
android:id="@+id/listView"
|
android:id="@+id/listView"
|
||||||
dslv:drag_enabled="true"
|
dslv:drag_enabled="true"
|
||||||
dslv:drag_start_mode="onLongPress"
|
dslv:drag_start_mode="onLongPress"
|
||||||
@@ -82,6 +82,7 @@
|
|||||||
style="?android:attr/progressBarStyleHorizontal"
|
style="?android:attr/progressBarStyleHorizontal"
|
||||||
android:layout_below="@+id/header"
|
android:layout_below="@+id/header"
|
||||||
android:layout_marginTop="@dimen/progressbarOffset"
|
android:layout_marginTop="@dimen/progressbarOffset"
|
||||||
|
android:visibility="gone"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
|||||||
@@ -22,4 +22,18 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
tools:context=".MainActivity">
|
tools:context=".MainActivity">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_add"
|
||||||
|
android:icon="?iconAdd"
|
||||||
|
android:title="@string/add_habit"
|
||||||
|
app:showAsAction="ifRoom"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_show_archived"
|
||||||
|
android:checkable="true"
|
||||||
|
android:enabled="true"
|
||||||
|
android:title="@string/show_archived"
|
||||||
|
android:orderInCategory="0"
|
||||||
|
app:showAsAction="never"/>
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
@@ -22,24 +22,12 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:context=".MainActivity">
|
tools:context=".MainActivity">
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_add"
|
|
||||||
android:icon="?iconAdd"
|
|
||||||
android:title="@string/add_habit"
|
|
||||||
app:showAsAction="ifRoom"/>
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_show_archived"
|
|
||||||
android:checkable="true"
|
|
||||||
android:enabled="true"
|
|
||||||
android:title="@string/show_archived"
|
|
||||||
app:showAsAction="never"/>
|
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_night_mode"
|
android:id="@+id/action_night_mode"
|
||||||
android:checkable="true"
|
android:checkable="true"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:title="@string/night_mode"
|
android:title="@string/night_mode"
|
||||||
|
android:orderInCategory="50"
|
||||||
app:showAsAction="never"/>
|
app:showAsAction="never"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
Reference in New Issue
Block a user