Making no-items view a bit friendlier
Also factoring out common activity elements to make consistent UI polish
easier to do.
Change-Id: If2d1d7907caa123e8424988ee3188ed0eef20fe1
diff --git a/app/src/androidTestMock/java/io/v/todos/MainActivityTest.java b/app/src/androidTestMock/java/io/v/todos/MainActivityTest.java
index c9b2dec..1e8956c 100644
--- a/app/src/androidTestMock/java/io/v/todos/MainActivityTest.java
+++ b/app/src/androidTestMock/java/io/v/todos/MainActivityTest.java
@@ -66,7 +66,7 @@
private MainPersistence mockPersistence() {
MainPersistence mocked = mock(MainPersistence.class);
- mActivity.setMainPersistence(mocked);
+ mActivity.setPersistence(mocked);
return mocked;
}
diff --git a/app/src/androidTestMock/java/io/v/todos/TodoListActivityTest.java b/app/src/androidTestMock/java/io/v/todos/TodoListActivityTest.java
index afc1446..3fd8212 100644
--- a/app/src/androidTestMock/java/io/v/todos/TodoListActivityTest.java
+++ b/app/src/androidTestMock/java/io/v/todos/TodoListActivityTest.java
@@ -68,7 +68,7 @@
private TodoListPersistence mockPersistence() {
TodoListPersistence mocked = mock(TodoListPersistence.class);
- mActivity.setTodoListPersistence(mocked);
+ mActivity.setPersistence(mocked);
return mocked;
}
diff --git a/app/src/main/java/io/v/todos/MainActivity.java b/app/src/main/java/io/v/todos/MainActivity.java
index 878f28f..7ca7d88 100644
--- a/app/src/main/java/io/v/todos/MainActivity.java
+++ b/app/src/main/java/io/v/todos/MainActivity.java
@@ -4,7 +4,6 @@
package io.v.todos;
-import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.VisibleForTesting;
@@ -13,7 +12,6 @@
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-import android.widget.Toolbar;
import io.v.todos.model.DataList;
import io.v.todos.model.ListMetadata;
@@ -32,36 +30,20 @@
*
* @author alexfandrianto
*/
-public class MainActivity extends Activity {
- private MainPersistence mPersistence;
-
+public class MainActivity extends TodosAppActivity<MainPersistence, TodoListRecyclerAdapter> {
// Snackoos are the code name for the list of todos.
// These todos are backed up at the SNACKOOS child of the Firebase URL.
// We use mMainList to track a custom sorted list of the stored values.
static final String INTENT_SNACKOO_KEY = "snackoo key";
private DataList<ListMetadata> mMainList = new DataList<>();
- // This adapter handle mirrors the firebase list values and generates the corresponding todo
- // item View children for a list view.
- private TodoListRecyclerAdapter mAdapter;
private RecyclerView mRecyclerView;
@Override
- protected void onDestroy() {
- if (mPersistence != null) {
- mPersistence.close();
- mPersistence = null;
- }
- super.onDestroy();
- }
-
- @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setActionBar(toolbar);
getActionBar().setTitle(R.string.app_name);
+ mEmptyView.setText(R.string.no_lists);
// Set up the todo list adapter
mAdapter = new TodoListRecyclerAdapter(mMainList, new View.OnClickListener() {
@@ -164,18 +146,6 @@
};
}
- // Allow the tests to mock out the main persistence.
- @VisibleForTesting
- void setMainPersistence(MainPersistence p) {
- mPersistence = p;
- }
-
- // Set the visibility based on what the adapter thinks is the visible item count.
- private void setEmptyVisiblity() {
- View v = findViewById(R.id.empty);
- v.setVisibility(mAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
- }
-
public void initiateItemAdd(View view) {
UIUtil.showAddDialog(this, "New Todo List", new UIUtil.DialogResponseListener() {
@Override
diff --git a/app/src/main/java/io/v/todos/TodoListActivity.java b/app/src/main/java/io/v/todos/TodoListActivity.java
index 454884d..e47cf53 100644
--- a/app/src/main/java/io/v/todos/TodoListActivity.java
+++ b/app/src/main/java/io/v/todos/TodoListActivity.java
@@ -4,7 +4,6 @@
package io.v.todos;
-import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.VisibleForTesting;
@@ -13,13 +12,11 @@
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-import android.widget.Toolbar;
import io.v.todos.model.DataList;
import io.v.todos.model.ListSpec;
import io.v.todos.model.Task;
import io.v.todos.model.TaskSpec;
-import io.v.todos.persistence.MainPersistence;
import io.v.todos.persistence.PersistenceFactory;
import io.v.todos.persistence.TodoListListener;
import io.v.todos.persistence.TodoListPersistence;
@@ -36,40 +33,22 @@
*
* @author alexfandrianto
*/
-public class TodoListActivity extends Activity {
- private TodoListPersistence mPersistence;
-
+public class TodoListActivity extends TodosAppActivity<TodoListPersistence, TaskRecyclerAdapter> {
private ListSpec snackoo;
private DataList<Task> snackoosList = new DataList<>();
- // This adapter handle mirrors the firebase list values and generates the corresponding todo
- // item View children for a list view.
- private TaskRecyclerAdapter adapter;
-
// The menu item that toggles whether done items are shown or not.
private MenuItem mShowDoneMenuItem;
- @Override
- protected void onDestroy() {
- if (mPersistence != null) {
- mPersistence.close();
- mPersistence = null;
- }
- super.onDestroy();
- }
-
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
+ mEmptyView.setText(R.string.no_tasks);
Intent intent = getIntent();
final String snackooKey = intent.getStringExtra(MainActivity.INTENT_SNACKOO_KEY);
- Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
- setActionBar(toolbar);
-
// Set up the todo list adapter
- adapter = new TaskRecyclerAdapter(snackoosList, new View.OnClickListener() {
+ mAdapter = new TaskRecyclerAdapter(snackoosList, new View.OnClickListener() {
@Override
public void onClick(View view) {
String key = (String) view.getTag();
@@ -79,7 +58,7 @@
});
RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler);
- recyclerView.setAdapter(adapter);
+ recyclerView.setAdapter(mAdapter);
new ItemTouchHelper(new SwipeableTouchHelperCallback() {
@Override
@@ -129,13 +108,13 @@
mShowDoneMenuItem.setChecked(showDone);
}
- int oldSize = adapter.getItemCount();
- adapter.setShowDone(showDone);
- int newSize = adapter.getItemCount();
+ int oldSize = mAdapter.getItemCount();
+ mAdapter.setShowDone(showDone);
+ int newSize = mAdapter.getItemCount();
if (newSize > oldSize) {
- adapter.notifyItemRangeInserted(oldSize, newSize - oldSize);
+ mAdapter.notifyItemRangeInserted(oldSize, newSize - oldSize);
} else {
- adapter.notifyItemRangeRemoved(newSize, oldSize - newSize);
+ mAdapter.notifyItemRangeRemoved(newSize, oldSize - newSize);
}
setEmptyVisiblity();
}
@@ -143,7 +122,7 @@
@Override
public void onItemAdd(Task item) {
int position = snackoosList.insertInOrder(item);
- adapter.notifyItemInserted(position);
+ mAdapter.notifyItemInserted(position);
setEmptyVisiblity();
}
@@ -151,32 +130,20 @@
public void onItemUpdate(Task item) {
int start = snackoosList.findIndexByKey(item.key);
int end = snackoosList.updateInOrder(item);
- adapter.notifyItemMoved(start, end);
- adapter.notifyItemChanged(end);
+ mAdapter.notifyItemMoved(start, end);
+ mAdapter.notifyItemChanged(end);
setEmptyVisiblity();
}
@Override
public void onItemDelete(String key) {
int position = snackoosList.removeByKey(key);
- adapter.notifyItemRemoved(position);
+ mAdapter.notifyItemRemoved(position);
setEmptyVisiblity();
}
};
}
- // Allow the tests to mock out the main persistence.
- @VisibleForTesting
- void setTodoListPersistence(TodoListPersistence p) {
- mPersistence = p;
- }
-
- // Set the visibility based on what the adapter thinks is the visible item count.
- private void setEmptyVisiblity() {
- View v = findViewById(R.id.empty);
- v.setVisibility(adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
- }
-
public void initiateItemAdd(View view) {
UIUtil.showAddDialog(this, "New Task", new UIUtil.DialogResponseListener() {
@Override
@@ -226,7 +193,7 @@
mShowDoneMenuItem = menu.findItem(R.id.show_done);
// Since the menu item may be inflated too late, set checked to the adapter's value.
- mShowDoneMenuItem.setChecked(adapter.getShowDone());
+ mShowDoneMenuItem.setChecked(mAdapter.getShowDone());
return true;
}
diff --git a/app/src/main/java/io/v/todos/TodosAppActivity.java b/app/src/main/java/io/v/todos/TodosAppActivity.java
new file mode 100644
index 0000000..0991262
--- /dev/null
+++ b/app/src/main/java/io/v/todos/TodosAppActivity.java
@@ -0,0 +1,57 @@
+// Copyright 2016 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package io.v.todos;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.Toolbar;
+
+import io.v.todos.persistence.Persistence;
+
+public class TodosAppActivity<P extends Persistence, A extends RecyclerView.Adapter<?>>
+ extends Activity {
+ protected P mPersistence;
+ protected A mAdapter;
+
+ protected TextView mEmptyView;
+
+ /**
+ * Allow tests to mock out persistence.
+ */
+ @VisibleForTesting
+ void setPersistence(P persistence) {
+ mPersistence = persistence;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setActionBar(toolbar);
+
+ mEmptyView = (TextView) findViewById(R.id.empty);
+ }
+
+ @Override
+ protected void onDestroy() {
+ if (mPersistence != null) {
+ mPersistence.close();
+ mPersistence = null;
+ }
+ super.onDestroy();
+ }
+
+ /**
+ * Set the visibility based on what the adapter thinks is the visible item count.
+ */
+ protected void setEmptyVisiblity() {
+ mEmptyView.setVisibility(mAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
+ }
+}
diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml
index f1a47c2..c014941 100644
--- a/app/src/main/res/layout/content_main.xml
+++ b/app/src/main/res/layout/content_main.xml
@@ -1,40 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- app:layout_behavior="@string/appbar_scrolling_view_behavior"
- tools:context="io.v.todos.MainActivity"
- tools:showIn="@layout/activity_main">
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior"
+ tools:context="io.v.todos.MainActivity"
+ tools:showIn="@layout/activity_main">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
- <android.support.v7.widget.RecyclerView android:id="@+id/recycler"
+
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
- app:layoutManager="LinearLayoutManager" />
- <TextView android:id="@+id/empty"
+ app:layoutManager="LinearLayoutManager"/>
+
+ <TextView
+ android:id="@+id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="#FF0000"
- android:text="No data"/>
+ android:gravity="center"/>
</LinearLayout>
- <android.support.design.widget.FloatingActionButton android:id="@+id/fab"
- android:layout_height="wrap_content"
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/fab"
android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
- app:fabSize="normal"
- android:src="@android:drawable/ic_input_add"
android:layout_margin="@dimen/fab_margin"
android:clickable="true"
- android:onClick="initiateItemAdd"/>
+ android:onClick="initiateItemAdd"
+ android:src="@android:drawable/ic_input_add"
+ app:fabSize="normal"/>
</RelativeLayout>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index da00730..7cd0203 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -7,6 +7,8 @@
<string name="set_button">Set</string>
<string name="add_button">Add</string>
<string name="init_persistence">Initializing…</string>
+ <string name="no_lists">No todo lists.\nPress \'+\' to add lists.</string>
+ <string name="no_tasks">No tasks.\nPress \'+\' to add tasks.</string>
<!-- Errors -->
<string name="err_init">Unable to initialize persistence</string>
<string name="err_sync">Unable to sync</string>