From f9933bf2e70a613eefd1e8bf52d478f792bad61f Mon Sep 17 00:00:00 2001 From: AndyScherzinger Date: Sat, 16 Dec 2017 18:10:32 +0100 Subject: [PATCH 1/2] new take on the drawer menu implementation --- app/build.gradle | 2 +- app/src/main/AndroidManifest.xml | 3 +- .../android/activity/DrawerActivity.java | 291 ++++++++++++++++++ .../activity/NotesListViewActivity.java | 53 +--- app/src/main/res/drawable/drawer_icon.xml | 10 + .../main/res/drawable/file_document_box.xml | 8 + .../main/res/drawable/information_outline.xml | 8 + app/src/main/res/drawable/settings.xml | 2 +- .../res/layout/activity_notes_list_view.xml | 21 +- app/src/main/res/layout/drawer_header.xml | 39 +++ app/src/main/res/layout/toolbar.xml | 18 ++ .../main/res/menu/menu_drawer_list_view.xml | 25 ++ app/src/main/res/menu/menu_list_view.xml | 13 +- app/src/main/res/values/dimens.xml | 2 + app/src/main/res/values/strings.xml | 5 + app/src/main/res/values/styles.xml | 18 ++ build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +- 18 files changed, 451 insertions(+), 73 deletions(-) create mode 100644 app/src/main/java/it/niedermann/owncloud/notes/android/activity/DrawerActivity.java create mode 100644 app/src/main/res/drawable/drawer_icon.xml create mode 100644 app/src/main/res/drawable/file_document_box.xml create mode 100644 app/src/main/res/drawable/information_outline.xml create mode 100644 app/src/main/res/layout/drawer_header.xml create mode 100644 app/src/main/res/layout/toolbar.xml create mode 100644 app/src/main/res/menu/menu_drawer_list_view.xml diff --git a/app/build.gradle b/app/build.gradle index b492ef89f..57f78a5b4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion 25 - buildToolsVersion '25.0.1' + buildToolsVersion '26.0.2' defaultConfig { applicationId "it.niedermann.owncloud.notes" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 527951521..73cdd3277 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -17,7 +17,8 @@ + android:label="@string/app_name" + android:theme="@style/Nextcloud.NoActionBar"> diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/DrawerActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/DrawerActivity.java new file mode 100644 index 000000000..913af8695 --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/DrawerActivity.java @@ -0,0 +1,291 @@ +package it.niedermann.owncloud.notes.android.activity; + +import android.content.Intent; +import android.content.res.Configuration; +import android.graphics.Color; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.Handler; +import android.support.annotation.NonNull; +import android.support.design.widget.NavigationView; +import android.support.v4.graphics.drawable.DrawableCompat; +import android.support.v4.view.GravityCompat; +import android.support.v4.widget.DrawerLayout; +import android.support.v7.app.ActionBarDrawerToggle; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.text.Html; +import android.util.Log; +import android.view.MenuItem; +import android.view.View; + +import it.niedermann.owncloud.notes.R; + +/** + * Created by scherzia on 16.12.2017. + */ +public abstract class DrawerActivity extends AppCompatActivity { + private static final String TAG = DrawerActivity.class.getSimpleName(); + + public static final int RESULT_CODE_SERVER_SETTINGS = 2; + public static final int RESULT_CODE_ABOUT = 3; + + /** + * Reference to the drawer layout. + */ + protected DrawerLayout mDrawerLayout; + + /** + * Reference to the drawer toggle. + */ + protected ActionBarDrawerToggle mDrawerToggle; + + /** + * Reference to the navigation view. + */ + private NavigationView mNavigationView; + + /** + * Id of the checked menu item. + */ + private int mCheckedMenuItem; + + /** + * runnable that will be executed after the drawer has been closed. + */ + private Runnable pendingRunnable; + + /** + * Toolbar setup that must be called in implementer's {@link #onCreate} + * after {@link #setContentView} if they want to use the toolbar. + */ + protected void setupToolbar() { + Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + } + + /** + * Initializes the drawer, its content and highlights the menu item with the given id. + * This method needs to be called after the content view has been set. + * + * @param menuItemId the menu item to be checked/highlighted + */ + protected void setupDrawer(int menuItemId) { + setupDrawer(); + setDrawerMenuItemChecked(menuItemId); + } + + /** + * Initializes the drawer and its content. + * This method needs to be called after the content view has been set. + */ + protected void setupDrawer() { + mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); + + mNavigationView = (NavigationView) findViewById(R.id.nav_view); + if (mNavigationView != null) { + setupDrawerMenu(mNavigationView); + } + + if (getSupportActionBar() != null) { + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + + setupDrawerToggle(); + } + + /** + * setup drawer content, basically setting the item selected listener. + * + * @param navigationView the drawers navigation view + */ + protected void setupDrawerMenu(NavigationView navigationView) { + navigationView.setItemIconTintList(null); + + // setup actions for drawer menu items + navigationView.setNavigationItemSelectedListener( + new NavigationView.OnNavigationItemSelectedListener() { + @Override + public boolean onNavigationItemSelected(@NonNull final MenuItem menuItem) { + mDrawerLayout.closeDrawers(); + // pending runnable will be executed after the drawer has been closed + pendingRunnable = new Runnable() { + @Override + public void run() { + selectNavigationItem(menuItem); + } + }; + return true; + } + }); + } + + private void selectNavigationItem(final MenuItem menuItem) { + setDrawerMenuItemChecked(menuItem.getItemId()); + + switch (menuItem.getItemId()) { + case R.id.action_settings: + Intent settingsIntent = new Intent(this, SettingsActivity.class); + startActivityForResult(settingsIntent, RESULT_CODE_SERVER_SETTINGS); + break; + case R.id.action_about: + Intent aboutIntent = new Intent(this, AboutActivity.class); + startActivityForResult(aboutIntent, RESULT_CODE_ABOUT); + break; + default: + Log.w(TAG, "Unknown drawer menu item clicked: " + menuItem.getTitle()); + break; + } + } + + /** + * initializes and sets up the drawer toggle. + */ + private void setupDrawerToggle() { + mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.string.drawer_open, R.string.drawer_close) { + + /** Called when a drawer has settled in a completely closed state. */ + public void onDrawerClosed(View view) { + super.onDrawerClosed(view); + + supportInvalidateOptionsMenu(); + mDrawerToggle.setDrawerIndicatorEnabled(isDrawerIndicatorAvailable()); + + if (pendingRunnable != null) { + new Handler().post(pendingRunnable); + pendingRunnable = null; + } + + closeDrawer(); + } + + /** Called when a drawer has settled in a completely open state. */ + public void onDrawerOpened(View drawerView) { + super.onDrawerOpened(drawerView); + mDrawerToggle.setDrawerIndicatorEnabled(true); + supportInvalidateOptionsMenu(); + } + }; + + // Set the drawer toggle as the DrawerListener + mDrawerLayout.addDrawerListener(mDrawerToggle); + mDrawerToggle.setDrawerIndicatorEnabled(true); + mDrawerToggle.getDrawerArrowDrawable().setColor(Color.WHITE); + } + + @Override + public void onBackPressed() { + if (isDrawerOpen()) { + closeDrawer(); + return; + } + super.onBackPressed(); + } + + @Override + protected void onResume() { + super.onResume(); + setDrawerMenuItemChecked(mCheckedMenuItem); + } + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (mDrawerToggle != null) { + mDrawerToggle.syncState(); + } + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + if (mDrawerToggle != null) { + mDrawerToggle.onConfigurationChanged(newConfig); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + boolean retval = true; + switch (item.getItemId()) { + case android.R.id.home: { + if (isDrawerOpen()) { + closeDrawer(); + } else { + openDrawer(); + } + break; + } + default: + retval = super.onOptionsItemSelected(item); + break; + } + return retval; + } + + /** + * checks/highlights the provided menu item if the drawer has been initialized and the menu item exists. + * + * @param menuItemId the menu item to be highlighted + */ + protected void setDrawerMenuItemChecked(int menuItemId) { + if (mNavigationView != null && mNavigationView.getMenu() != null && + mNavigationView.getMenu().findItem(menuItemId) != null) { + + MenuItem item = mNavigationView.getMenu().findItem(menuItemId); + item.setChecked(true); + + // reset all tinted icons + for (int i = 0; i < mNavigationView.getMenu().size(); i++) { + MenuItem menuItem = mNavigationView.getMenu().getItem(i); + if (menuItem.getIcon() != null) { + menuItem.getIcon().clearColorFilter(); + } + } + + Drawable wrap = DrawableCompat.wrap(item.getIcon()); + wrap.setColorFilter(getResources().getColor(R.color.primary), PorterDuff.Mode.SRC_ATOP); + mCheckedMenuItem = menuItemId; + } else { + Log.w(TAG, "setDrawerMenuItemChecked has been called with invalid menu-item-ID"); + } + } + + /** + * checks if the drawer exists and is opened. + * + * @return true if the drawer is open, else false + */ + public boolean isDrawerOpen() { + return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(GravityCompat.START); + } + + /** + * opens the drawer. + */ + public void openDrawer() { + if (mDrawerLayout != null) { + mDrawerLayout.openDrawer(GravityCompat.START); + } + } + + /** + * closes the drawer. + */ + public void closeDrawer() { + if (mDrawerLayout != null) { + mDrawerLayout.closeDrawer(GravityCompat.START); + } + } + + /** + * always returns true and is provided to be overriden if an Activity + * needs a more fine grained logic on if/when to show the drawer icon. + * + * @return true + */ + public boolean isDrawerIndicatorAvailable() { + return true; + } +} diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java index 7917ab674..bf461ceba 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java @@ -48,7 +48,7 @@ import static android.os.Build.VERSION.SDK_INT; -public class NotesListViewActivity extends AppCompatActivity implements +public class NotesListViewActivity extends DrawerActivity implements ItemAdapter.NoteClickListener, View.OnClickListener { public final static String CREATED_NOTE = "it.niedermann.owncloud.notes.created_notes"; @@ -56,7 +56,6 @@ public class NotesListViewActivity extends AppCompatActivity implements private final static int create_note_cmd = 0; private final static int show_single_note_cmd = 1; - private final static int server_settings = 2; private final static int about = 3; private RecyclerView listView = null; @@ -87,7 +86,7 @@ protected void onCreate(Bundle savedInstanceState) { .getDefaultSharedPreferences(getApplicationContext()); if (!NoteServerSyncHelper.isConfigured(this)) { Intent settingsIntent = new Intent(this, SettingsActivity.class); - startActivityForResult(settingsIntent, server_settings); + startActivityForResult(settingsIntent, DrawerActivity.RESULT_CODE_SERVER_SETTINGS); } setContentView(R.layout.activity_notes_list_view); @@ -118,42 +117,10 @@ public void onRefresh() { // Show persistant notification for creating a new note checkNotificationSetting(); - initSidebar(); - } + // setup toolbar + setupToolbar(); - private void initSidebar() { - ListView mDrawerList = (ListView) findViewById(R.id.left_drawer); - mDrawerList.setAdapter(new ArrayAdapter<>(this, R.layout.fragment_drawer_item, new String[]{ - "Alle Notizen", - "Favoriten" - })); - final DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); - mDrawerList.setOnItemClickListener(new ListView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - if (SDK_INT >= 14) { - mDrawerLayout.closeDrawer(Gravity.START); - } else { - mDrawerLayout.closeDrawer(Gravity.LEFT); - } - } - }); - mDrawerLayout.addDrawerListener(new ActionBarDrawerToggle(this, mDrawerLayout, - R.string.drawer_opened, R.string.drawer_closed) { - public void onDrawerClosed(View view) { - super.onDrawerClosed(view); - getSupportActionBar().setTitle(mTitle); - invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu() - } - - public void onDrawerOpened(View drawerView) { - super.onDrawerOpened(drawerView); - getSupportActionBar().setTitle(mDrawerTitle); - invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu() - } - }); - - mTitle = mDrawerTitle = getTitle(); + setupDrawer(R.id.nav_all_notes); } protected void checkNotificationSetting() { @@ -333,14 +300,6 @@ protected void onNewIntent(Intent intent) { public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); switch (id) { - case R.id.action_settings: - Intent settingsIntent = new Intent(this, SettingsActivity.class); - startActivityForResult(settingsIntent, server_settings); - return true; - case R.id.action_about: - Intent aboutIntent = new Intent(this, AboutActivity.class); - startActivityForResult(aboutIntent, about); - return true; default: return super.onOptionsItemSelected(item); } @@ -380,7 +339,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { } } } - } else if (requestCode == server_settings) { + } else if (requestCode == DrawerActivity.RESULT_CODE_SERVER_SETTINGS) { // Create new Instance with new URL and credentials db = NoteSQLiteOpenHelper.getInstance(this); if (db.getNoteServerSyncHelper().isSyncPossible()) { diff --git a/app/src/main/res/drawable/drawer_icon.xml b/app/src/main/res/drawable/drawer_icon.xml new file mode 100644 index 000000000..a4038533f --- /dev/null +++ b/app/src/main/res/drawable/drawer_icon.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/file_document_box.xml b/app/src/main/res/drawable/file_document_box.xml new file mode 100644 index 000000000..2cebce701 --- /dev/null +++ b/app/src/main/res/drawable/file_document_box.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/information_outline.xml b/app/src/main/res/drawable/information_outline.xml new file mode 100644 index 000000000..a959129b1 --- /dev/null +++ b/app/src/main/res/drawable/information_outline.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/settings.xml b/app/src/main/res/drawable/settings.xml index 423f75660..ddab9c2db 100644 --- a/app/src/main/res/drawable/settings.xml +++ b/app/src/main/res/drawable/settings.xml @@ -5,6 +5,6 @@ android:viewportHeight="24" android:viewportWidth="24"> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_notes_list_view.xml b/app/src/main/res/layout/activity_notes_list_view.xml index 34ad329e8..627ad5496 100644 --- a/app/src/main/res/layout/activity_notes_list_view.xml +++ b/app/src/main/res/layout/activity_notes_list_view.xml @@ -11,10 +11,13 @@ android:layout_width="match_parent" android:layout_height="match_parent"> + + @@ -39,15 +42,17 @@ - + android:layout_weight="1" + android:fitsSystemWindows="true" + app:headerLayout="@layout/drawer_header" + app:menu="@menu/menu_drawer_list_view" + app:theme="@style/NavigationView_ItemTextAppearance"> + + \ No newline at end of file diff --git a/app/src/main/res/layout/drawer_header.xml b/app/src/main/res/layout/drawer_header.xml new file mode 100644 index 000000000..0b6c695c5 --- /dev/null +++ b/app/src/main/res/layout/drawer_header.xml @@ -0,0 +1,39 @@ + + + + + + + + diff --git a/app/src/main/res/layout/toolbar.xml b/app/src/main/res/layout/toolbar.xml new file mode 100644 index 000000000..8ef8378ae --- /dev/null +++ b/app/src/main/res/layout/toolbar.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/app/src/main/res/menu/menu_drawer_list_view.xml b/app/src/main/res/menu/menu_drawer_list_view.xml new file mode 100644 index 000000000..cd5cb9ffa --- /dev/null +++ b/app/src/main/res/menu/menu_drawer_list_view.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_list_view.xml b/app/src/main/res/menu/menu_list_view.xml index 6d7f8fbc9..0cc763f5e 100644 --- a/app/src/main/res/menu/menu_list_view.xml +++ b/app/src/main/res/menu/menu_list_view.xml @@ -5,19 +5,8 @@ tools:context="com.example.owncloudnotes.NotesListViewActivity"> - - \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 50c11bc94..e7b4d8977 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -9,4 +9,6 @@ 16dp 5dp + 140dp + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 68ef83e68..0c2abab57 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2,8 +2,10 @@ Notes + App icon No notes yet New note + Notes Settings Save Cancel @@ -25,6 +27,7 @@ Preview Share About + Search Copy @@ -102,6 +105,8 @@ Drawer opened Drawer closed + Drawer opened + Drawer closed diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index f728202be..15b1a66f5 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -13,6 +13,20 @@ @color/bg_normal + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 4c6a33fa7..f00b51f71 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { } dependencies { apply plugin: 'maven' - classpath 'com.android.tools.build:gradle:2.3.0' + classpath 'com.android.tools.build:gradle:3.0.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 37ec95a33..2508e5194 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Mar 03 15:22:24 CET 2017 +#Fri Dec 08 15:43:45 CET 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip From 61a6a20ade4afc76f496267b6d4b98d0378f57a1 Mon Sep 17 00:00:00 2001 From: AndyScherzinger Date: Sun, 17 Dec 2017 13:23:22 +0100 Subject: [PATCH 2/2] update build config --- .travis.yml | 2 +- build.gradle | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0145b0a1d..a644f5d17 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ jdk: oraclejdk8 android: components: - tools - - build-tools-25.0.1 + - build-tools-26.0.2 - android-25 - extra-android-m2repository diff --git a/build.gradle b/build.gradle index f00b51f71..421d036a6 100644 --- a/build.gradle +++ b/build.gradle @@ -3,6 +3,7 @@ buildscript { repositories { jcenter() + google() } dependencies { apply plugin: 'maven' @@ -16,5 +17,6 @@ buildscript { allprojects { repositories { jcenter() + google() } }