Partial bookmarks drawer implemention.
authorSoren Stoutner <soren@stoutner.com>
Fri, 6 Oct 2017 17:29:56 +0000 (10:29 -0700)
committerSoren Stoutner <soren@stoutner.com>
Fri, 6 Oct 2017 17:29:56 +0000 (10:29 -0700)
app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksActivity.java
app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java
app/src/main/res/layout/bookmarks_activity_item_linearlayout.xml [new file with mode: 0644]
app/src/main/res/layout/bookmarks_drawer_item_linearlayout.xml [new file with mode: 0644]
app/src/main/res/layout/bookmarks_item_linearlayout.xml [deleted file]
app/src/main/res/layout/main_drawerlayout.xml
app/src/main/res/layout/navigation_header.xml

index 8a69e2b..6ea013c 100644 (file)
@@ -132,7 +132,7 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
         // Display the home arrow on `SupportActionBar`.
         appBar.setDisplayHomeAsUpEnabled(true);
 
-        // Initialize the database helper and the `ListView`.  `this` specifies the context.  The two `nulls` do not specify the database name or a `CursorFactory`.
+        // Initialize the database helper.  `this` specifies the context.  The two `nulls` do not specify the database name or a `CursorFactory`.
         // The `0` specifies a database version, but that is ignored and set instead using a constant in `BookmarksDatabaseHelper`.
         bookmarksDatabaseHelper = new BookmarksDatabaseHelper(this, null, null, 0);
 
@@ -931,7 +931,7 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
             @Override
             public View newView(Context context, Cursor cursor, ViewGroup parent) {
                 // Inflate the individual item layout.  `false` does not attach it to the root.
-                return getLayoutInflater().inflate(R.layout.bookmarks_item_linearlayout, parent, false);
+                return getLayoutInflater().inflate(R.layout.bookmarks_activity_item_linearlayout, parent, false);
             }
 
             @Override
index 7549f5c..9dc3913 100644 (file)
@@ -34,6 +34,8 @@ import android.content.SharedPreferences;
 import android.content.res.Configuration;
 import android.database.Cursor;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Typeface;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
@@ -47,6 +49,7 @@ import android.print.PrintDocumentAdapter;
 import android.print.PrintManager;
 import android.support.annotation.NonNull;
 import android.support.design.widget.CoordinatorLayout;
+import android.support.design.widget.FloatingActionButton;
 import android.support.design.widget.NavigationView;
 import android.support.design.widget.Snackbar;
 import android.support.v4.app.ActivityCompat;
@@ -71,6 +74,7 @@ import android.view.Menu;
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.view.inputmethod.InputMethodManager;
 import android.webkit.CookieManager;
@@ -85,10 +89,13 @@ import android.webkit.WebStorage;
 import android.webkit.WebView;
 import android.webkit.WebViewClient;
 import android.webkit.WebViewDatabase;
+import android.widget.AdapterView;
+import android.widget.CursorAdapter;
 import android.widget.EditText;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
+import android.widget.ListView;
 import android.widget.ProgressBar;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
@@ -102,6 +109,7 @@ import com.stoutner.privacybrowser.dialogs.HttpAuthenticationDialog;
 import com.stoutner.privacybrowser.dialogs.PinnedSslCertificateMismatchDialog;
 import com.stoutner.privacybrowser.dialogs.UrlHistoryDialog;
 import com.stoutner.privacybrowser.dialogs.ViewSslCertificateDialog;
+import com.stoutner.privacybrowser.helpers.BookmarksDatabaseHelper;
 import com.stoutner.privacybrowser.helpers.DomainsDatabaseHelper;
 import com.stoutner.privacybrowser.helpers.OrbotProxyHelper;
 import com.stoutner.privacybrowser.dialogs.DownloadFileDialog;
@@ -328,6 +336,17 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
     // `pinnedDomainSslCertificate` is used in `onCreate()` and `applyDomainSettings()`.
     private boolean pinnedDomainSslCertificate;
 
+    // `bookmarksDatabaseHelper` is used in `onCreate()` and `loadBookmarksFolder()`.
+    private BookmarksDatabaseHelper bookmarksDatabaseHelper;
+
+    // `bookmarksListView` is used in `onCreate()` and `loadBookmarksFolder()`.
+    private ListView bookmarksListView;
+
+    // `currentBookmarksFolder` is used in `onCreate()`, `onBackPressed()`, and `loadBookmarksFolder()`.
+    private String currentBookmarksFolder;
+
+    // `bookmarksTitleTextView` is used in `onCreate()` and `loadBookmarksFolder()`.
+    private TextView bookmarksTitleTextView;
 
     @Override
     // Remove Android Studio's warning about the dangers of using SetJavaScriptEnabled.  The whole premise of Privacy Browser is built around an understanding of these dangers.
@@ -357,7 +376,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         // Get a handle for `inputMethodManager`.
         inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
 
-        // We need to use the `SupportActionBar` from `android.support.v7.app.ActionBar` until the minimum API is >= 21.
+        // `SupportActionBar` from `android.support.v7.app.ActionBar` must be used until the minimum API is >= 21.
         supportAppBar = (Toolbar) findViewById(R.id.app_bar);
         setSupportActionBar(supportAppBar);
         appBar = getSupportActionBar();
@@ -446,6 +465,10 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         // Get handles for views that need to be accessed.
         drawerLayout = (DrawerLayout) findViewById(R.id.drawerlayout);
         rootCoordinatorLayout = (CoordinatorLayout) findViewById(R.id.root_coordinatorlayout);
+        bookmarksListView = (ListView) findViewById(R.id.bookmarks_drawer_listview);
+        bookmarksTitleTextView = (TextView) findViewById(R.id.bookmarks_title_textview);
+        FloatingActionButton createBookmarksFolderFab = (FloatingActionButton) findViewById(R.id.create_bookmark_folder_fab);
+        FloatingActionButton createBookmarkFab = (FloatingActionButton) findViewById(R.id.create_bookmark_fab);
         mainWebViewRelativeLayout = (RelativeLayout) findViewById(R.id.main_webview_relativelayout);
         mainWebView = (WebView) findViewById(R.id.main_webview);
         findOnPageLinearLayout = (LinearLayout) findViewById(R.id.find_on_page_linearlayout);
@@ -454,6 +477,17 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         urlAppBarRelativeLayout = (RelativeLayout) findViewById(R.id.url_app_bar_relativelayout);
         favoriteIconImageView = (ImageView) findViewById(R.id.favorite_icon);
 
+        // Set the bookmarks drawer resources according to the theme.  This can't be done in the layout due to compatibility issues with the `DrawerLayout` support widget.
+        if (darkTheme) {
+            createBookmarksFolderFab.setImageDrawable(getResources().getDrawable(R.drawable.create_folder_dark));
+            createBookmarkFab.setImageDrawable(getResources().getDrawable(R.drawable.create_bookmark_dark));
+            bookmarksListView.setBackgroundColor(getResources().getColor(R.color.gray_850));
+        } else {
+            createBookmarksFolderFab.setImageDrawable(getResources().getDrawable(R.drawable.create_folder_light));
+            createBookmarkFab.setImageDrawable(getResources().getDrawable(R.drawable.create_bookmark_light));
+            bookmarksListView.setBackgroundColor(getResources().getColor(R.color.white));
+        }
+
         // Create a double-tap listener to toggle full-screen mode.
         final GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
             // Override `onDoubleTap()`.  All other events are handled using the default settings.
@@ -606,8 +640,9 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
             }
         });
 
-        // `DrawerTitle` identifies the `DrawerLayout` in accessibility mode.
+        // `DrawerTitle` identifies the `DrawerLayouts` in accessibility mode.
         drawerLayout.setDrawerTitle(GravityCompat.START, getString(R.string.navigation_drawer));
+        drawerLayout.setDrawerTitle(GravityCompat.END, getString(R.string.bookmarks));
 
         // Listen for touches on the navigation menu.
         final NavigationView navigationView = (NavigationView) findViewById(R.id.navigationview);
@@ -619,6 +654,49 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         final MenuItem navigationForwardMenuItem = navigationMenu.getItem(2);
         final MenuItem navigationHistoryMenuItem = navigationMenu.getItem(3);
 
+        // Initialize the bookmarks database helper.  `this` specifies the context.  The two `nulls` do not specify the database name or a `CursorFactory`.
+        // The `0` specifies a database version, but that is ignored and set instead using a constant in `BookmarksDatabaseHelper`.
+        bookmarksDatabaseHelper = new BookmarksDatabaseHelper(this, null, null, 0);
+
+        // Initialize `currentBookmarksFolder`.  `""` is the home folder in the database.
+        currentBookmarksFolder = "";
+
+        // Load the home folder, which is `""` in the database.
+        loadBookmarksFolder();
+
+        bookmarksListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                // Convert the id from long to int to match the format of the bookmarks database.
+                int databaseID = (int) id;
+
+                // Get the bookmark `Cursor` for this ID and move it to the first row.
+                Cursor bookmarkCursor = bookmarksDatabaseHelper.getBookmarkCursor(databaseID);
+                bookmarkCursor.moveToFirst();
+
+                // Act upon the bookmark according to the type.
+                if (bookmarkCursor.getInt(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)) == 1) {  // The selected bookmark is a folder.
+                    // Store the new folder name in `currentBookmarksFolder`.
+                    currentBookmarksFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+
+                    // Load the new folder.
+                    loadBookmarksFolder();
+                } else {  // The selected bookmark is not a folder.
+                    // Get the bookmark URL and assign it to `formattedUrlString`.
+                    String bookmarkUrl = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL));
+
+                    // Load the bookmark URL.
+                    loadUrl(bookmarkUrl);
+
+                    // Close the bookmarks drawer.
+                    drawerLayout.closeDrawer(GravityCompat.END);
+                }
+
+                // Close the `Cursor`.
+                bookmarkCursor.close();
+            }
+        });
+
         // The `DrawerListener` allows us to update the Navigation Menu.
         drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
             @Override
@@ -2324,21 +2402,30 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
     // Override `onBackPressed` to handle the navigation drawer and `mainWebView`.
     @Override
     public void onBackPressed() {
-        // Close the navigation drawer if it is available.  GravityCompat.START is the drawer on the left on Left-to-Right layout text.
-        if (drawerLayout.isDrawerVisible(GravityCompat.START)) {
+        if (drawerLayout.isDrawerVisible(GravityCompat.START)) {  // The navigation drawer is open.
+            // Close the navigation drawer.
             drawerLayout.closeDrawer(GravityCompat.START);
-        } else {
-            // Load the previous URL if available.
-            if (mainWebView.canGoBack()) {
-                // Set `navigatingHistory` so that the domain settings are applied when the new URL is loaded.
-                navigatingHistory = true;
-
-                // Go back.
-                mainWebView.goBack();
-            } else {
-                // Pass `onBackPressed()` to the system.
-                super.onBackPressed();
+        } else if (drawerLayout.isDrawerVisible(GravityCompat.END)){  // The bookmarks drawer is open.
+            if (currentBookmarksFolder.isEmpty()) {  // The home folder is displayed.
+                // close the bookmarks drawer.
+                drawerLayout.closeDrawer(GravityCompat.END);
+            } else {  // A subfolder is displayed.
+                // Place the former parent folder in `currentFolder`.
+                currentBookmarksFolder = bookmarksDatabaseHelper.getParentFolder(currentBookmarksFolder);
+
+                // Load the new folder.
+                loadBookmarksFolder();
             }
+
+        } else if (mainWebView.canGoBack()) {  // There is at least one item in the `WebView` history.
+            // Set `navigatingHistory` so that the domain settings are applied when the new URL is loaded.
+            navigatingHistory = true;
+
+            // Go back.
+            mainWebView.goBack();
+        } else {  // There isn't anything to do in Privacy Browser.
+            // Pass `onBackPressed()` to the system.
+            super.onBackPressed();
         }
     }
 
@@ -2967,4 +3054,55 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
             urlTextBox.getText().setSpan(finalGrayColorSpan, endOfDomainName, urlString.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
         }
     }
+
+    private void loadBookmarksFolder() {
+        // Update `bookmarksCursor` with the contents of the bookmarks database for the current folder.
+        Cursor bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursorByDisplayOrder(currentBookmarksFolder);
+
+        // Setup a `CursorAdapter`.  `this` specifies the `Context`.  `false` disables `autoRequery`.
+        CursorAdapter bookmarksCursorAdapter = new CursorAdapter(this, bookmarksCursor, false) {
+            @Override
+            public View newView(Context context, Cursor cursor, ViewGroup parent) {
+                // Inflate the individual item layout.  `false` does not attach it to the root.
+                return getLayoutInflater().inflate(R.layout.bookmarks_drawer_item_linearlayout, parent, false);
+            }
+
+            @Override
+            public void bindView(View view, Context context, Cursor cursor) {
+                // Get handles for the views.
+                ImageView bookmarkFavoriteIcon = (ImageView) view.findViewById(R.id.bookmark_favorite_icon);
+                TextView bookmarkNameTextView = (TextView) view.findViewById(R.id.bookmark_name);
+
+                // Get the favorite icon byte array from the `Cursor`.
+                byte[] favoriteIconByteArray = cursor.getBlob(cursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON));
+
+                // Convert the byte array to a `Bitmap` beginning at the first byte and ending at the last.
+                Bitmap favoriteIconBitmap = BitmapFactory.decodeByteArray(favoriteIconByteArray, 0, favoriteIconByteArray.length);
+
+                // Display the bitmap in `bookmarkFavoriteIcon`.
+                bookmarkFavoriteIcon.setImageBitmap(favoriteIconBitmap);
+
+                // Get the bookmark name from the cursor and display it in `bookmarkNameTextView`.
+                String bookmarkNameString = cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+                bookmarkNameTextView.setText(bookmarkNameString);
+
+                // Make the font bold for folders.
+                if (cursor.getInt(cursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)) == 1) {
+                    bookmarkNameTextView.setTypeface(Typeface.DEFAULT_BOLD);
+                } else {  // Reset the font to default for normal bookmarks.
+                    bookmarkNameTextView.setTypeface(Typeface.DEFAULT);
+                }
+            }
+        };
+
+        // Populate the `ListView` with the adapter.
+        bookmarksListView.setAdapter(bookmarksCursorAdapter);
+
+        // Set the bookmarks drawer title.
+        if (currentBookmarksFolder.isEmpty()) {
+            bookmarksTitleTextView.setText(R.string.bookmarks);
+        } else {
+            bookmarksTitleTextView.setText(currentBookmarksFolder);
+        }
+    }
 }
diff --git a/app/src/main/res/layout/bookmarks_activity_item_linearlayout.xml b/app/src/main/res/layout/bookmarks_activity_item_linearlayout.xml
new file mode 100644 (file)
index 0000000..6cd123d
--- /dev/null
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright © 2016-2017 Soren Stoutner <soren@stoutner.com>.
+
+  This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+
+  Privacy Browser 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.
+
+  Privacy Browser 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 Privacy Browser.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<!-- `tools:ignore="UseCompoundDrawables"` removes the lint warning about using a compound drawable, which doesn't work well with the layout options on the `ImageView`. -->
+<LinearLayout
+    android:id="@+id/bookmarks_item_linearlayout"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:orientation="horizontal"
+    android:background="?attr/listSelectorDrawable"
+    tools:ignore="UseCompoundDrawables" >
+
+    <ImageView
+        android:id="@+id/bookmark_favorite_icon"
+        android:layout_height="30dp"
+        android:layout_width="30dp"
+        android:layout_gravity="center_vertical"
+        android:layout_marginStart="10dp"
+        tools:ignore="ContentDescription" />
+
+    <TextView
+        android:id="@+id/bookmark_name"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:textColor="?android:attr/textColorPrimary"
+        android:textSize="22sp"
+        android:layout_margin="10dp"
+        android:maxLines="1"
+        android:ellipsize="end" />
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/bookmarks_drawer_item_linearlayout.xml b/app/src/main/res/layout/bookmarks_drawer_item_linearlayout.xml
new file mode 100644 (file)
index 0000000..3009a35
--- /dev/null
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright © 2016-2017 Soren Stoutner <soren@stoutner.com>.
+
+  This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+
+  Privacy Browser 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.
+
+  Privacy Browser 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 Privacy Browser.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<!-- `tools:ignore="UseCompoundDrawables"` removes the lint warning about using a compound drawable, which doesn't work well with the layout options on the `ImageView`. -->
+<LinearLayout
+    android:id="@+id/bookmarks_item_linearlayout"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:orientation="horizontal"
+    tools:ignore="UseCompoundDrawables" >
+
+    <ImageView
+        android:id="@+id/bookmark_favorite_icon"
+        android:layout_height="30dp"
+        android:layout_width="30dp"
+        android:layout_gravity="center_vertical"
+        android:layout_marginStart="10dp"
+        tools:ignore="ContentDescription" />
+
+    <TextView
+        android:id="@+id/bookmark_name"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:textColor="?android:attr/textColorPrimary"
+        android:textSize="22sp"
+        android:layout_margin="10dp"
+        android:maxLines="1"
+        android:ellipsize="end" />
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/bookmarks_item_linearlayout.xml b/app/src/main/res/layout/bookmarks_item_linearlayout.xml
deleted file mode 100644 (file)
index 9a27fb9..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-  Copyright © 2016-2017 Soren Stoutner <soren@stoutner.com>.
-
-  This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
-
-  Privacy Browser 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.
-
-  Privacy Browser 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 Privacy Browser.  If not, see <http://www.gnu.org/licenses/>. -->
-
-<LinearLayout
-    android:id="@+id/bookmarks_item_linearlayout"
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_height="wrap_content"
-    android:layout_width="match_parent"
-    android:orientation="horizontal"
-    android:background="?attr/listSelectorDrawable" >
-
-    <ImageView
-        android:id="@+id/bookmark_favorite_icon"
-        android:layout_height="30dp"
-        android:layout_width="30dp"
-        android:layout_gravity="center_vertical"
-        android:layout_marginStart="10dp"
-        tools:ignore="ContentDescription" />
-
-    <TextView
-        android:id="@+id/bookmark_name"
-        android:layout_height="wrap_content"
-        android:layout_width="wrap_content"
-        android:textColor="?android:attr/textColorPrimary"
-        android:textSize="22sp"
-        android:layout_margin="10dp"
-        android:maxLines="1"
-        android:ellipsize="end" />
-</LinearLayout>
\ No newline at end of file
index c138a3b..6339a31 100644 (file)
         app:headerLayout="@layout/navigation_header"
         app:menu="@menu/webview_navigation_menu"
         app:itemIconTint="?attr/navigationIconTintColor" />
+
+    <!-- The bookmarks drawer. -->
+    <FrameLayout
+        android:id="@+id/bookmarks_framelayout"
+        android:layout_height="match_parent"
+        android:layout_width="wrap_content"
+        android:layout_gravity="end" >
+
+        <LinearLayout
+            android:layout_height="match_parent"
+            android:layout_width="wrap_content"
+            android:orientation="vertical" >
+
+            <TextView
+                android:id="@+id/bookmarks_title_textview"
+                android:layout_height="wrap_content"
+                android:layout_width="match_parent"
+                android:paddingTop="35dp"
+                android:paddingBottom="8dp"
+                android:paddingStart="15dp"
+                android:paddingEnd="15dp"
+                android:textStyle="bold"
+                android:textSize="20sp"
+                android:background="?attr/navigationHeaderBackground"
+                android:textColor="?attr/navigationHeaderTextColor" />
+
+            <ListView
+                android:id="@+id/bookmarks_drawer_listview"
+                android:layout_height="0dp"
+                android:layout_width="match_parent"
+                android:layout_weight="1"
+                android:divider="@color/transparent"
+                android:dividerHeight="0dp" />
+        </LinearLayout>
+
+        <android.support.design.widget.FloatingActionButton
+            android:id="@+id/create_bookmark_folder_fab"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:layout_gravity="bottom|end"
+            android:layout_marginEnd="16dp"
+            android:layout_marginBottom="85dp" />
+
+        <android.support.design.widget.FloatingActionButton
+            android:id="@+id/create_bookmark_fab"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:layout_gravity="bottom|end"
+            android:layout_margin="16dp" />
+    </FrameLayout>
 </android.support.v4.widget.DrawerLayout>
\ No newline at end of file
index b1229d8..757cde4 100644 (file)
@@ -21,8 +21,8 @@
 <TextView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/navigationText"
-    android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:layout_width="match_parent"
     android:text="@string/navigation"
     android:paddingTop="35dp"
     android:paddingBottom="8dp"