Browse Source

Drawer implementation

Jason Skuby 8 years ago
parent
commit
b96c05fd8d

+ 53
- 4
android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java View File

1
 package com.reactnativenavigation.activities;
1
 package com.reactnativenavigation.activities;
2
 
2
 
3
 import android.content.Intent;
3
 import android.content.Intent;
4
+import android.content.res.Configuration;
4
 import android.os.Build;
5
 import android.os.Build;
5
 import android.os.Bundle;
6
 import android.os.Bundle;
6
 import android.os.Handler;
7
 import android.os.Handler;
7
 import android.provider.Settings;
8
 import android.provider.Settings;
8
 import android.support.annotation.CallSuper;
9
 import android.support.annotation.CallSuper;
10
+import android.support.v7.app.ActionBarDrawerToggle;
9
 import android.support.v7.app.AppCompatActivity;
11
 import android.support.v7.app.AppCompatActivity;
10
 import android.util.Log;
12
 import android.util.Log;
11
 import android.view.KeyEvent;
13
 import android.view.KeyEvent;
48
     protected static final String KEY_ANIMATED = "animated";
50
     protected static final String KEY_ANIMATED = "animated";
49
     protected static final String KEY_BADGE = "badge";
51
     protected static final String KEY_BADGE = "badge";
50
     protected static final String KEY_HIDDEN = "hidden";
52
     protected static final String KEY_HIDDEN = "hidden";
53
+    protected static final String KEY_SIDE = "side";
51
     protected static final String KEY_TAB_INDEX = "tabIndex";
54
     protected static final String KEY_TAB_INDEX = "tabIndex";
52
     protected static final String KEY_TITLE = "title";
55
     protected static final String KEY_TITLE = "title";
56
+    protected static final String KEY_TO = "to";
53
     private static final String TAG = "BaseReactActivity";
57
     private static final String TAG = "BaseReactActivity";
54
     private static final String REDBOX_PERMISSION_MESSAGE =
58
     private static final String REDBOX_PERMISSION_MESSAGE =
55
             "Overlay permissions needs to be granted in order for react native apps to run in dev mode";
59
             "Overlay permissions needs to be granted in order for react native apps to run in dev mode";
59
     private boolean mDoRefresh = false;
63
     private boolean mDoRefresh = false;
60
     private Menu mMenu;
64
     private Menu mMenu;
61
     protected RnnToolBar mToolbar;
65
     protected RnnToolBar mToolbar;
66
+    protected ActionBarDrawerToggle mDrawerToggle;
62
 
67
 
63
     /**
68
     /**
64
      * Returns the name of the bundle in assets. If this is null, and no file path is specified for
69
      * Returns the name of the bundle in assets. If this is null, and no file path is specified for
223
 
228
 
224
             if (getCurrentNavigatorId().equals(screen.navigatorId) &&
229
             if (getCurrentNavigatorId().equals(screen.navigatorId) &&
225
                 getScreenStackSize() >= 1) {
230
                 getScreenStackSize() >= 1) {
226
-                mToolbar.showBackButton(screen);
231
+                mToolbar.setNavUpButton(screen);
227
             }
232
             }
228
         }
233
         }
229
     }
234
     }
233
         if (mToolbar != null &&
238
         if (mToolbar != null &&
234
             getCurrentNavigatorId().equals(navigatorId) &&
239
             getCurrentNavigatorId().equals(navigatorId) &&
235
             getScreenStackSize() <= 2) {
240
             getScreenStackSize() <= 2) {
236
-            mToolbar.hideBackButton();
241
+            mToolbar.setNavUpButton();
237
         }
242
         }
243
+
238
         return null;
244
         return null;
239
     }
245
     }
240
 
246
 
241
     @CallSuper
247
     @CallSuper
242
     public Screen popToRoot(String navigatorId) {
248
     public Screen popToRoot(String navigatorId) {
243
         if (mToolbar != null) {
249
         if (mToolbar != null) {
244
-            mToolbar.hideBackButton();
250
+            mToolbar.setNavUpButton();
245
         }
251
         }
246
 
252
 
247
         return null;
253
         return null;
251
     public Screen resetTo(Screen screen) {
257
     public Screen resetTo(Screen screen) {
252
         StyleHelper.updateStyles(mToolbar, screen);
258
         StyleHelper.updateStyles(mToolbar, screen);
253
         if (mToolbar != null) {
259
         if (mToolbar != null) {
254
-            mToolbar.hideBackButton();
260
+            mToolbar.setNavUpButton();
255
         }
261
         }
256
 
262
 
257
         return null;
263
         return null;
273
 
279
 
274
     public abstract int getScreenStackSize();
280
     public abstract int getScreenStackSize();
275
 
281
 
282
+    @Override
283
+    public void onConfigurationChanged(Configuration newConfig) {
284
+        super.onConfigurationChanged(newConfig);
285
+        if (mDrawerToggle != null) {
286
+            mDrawerToggle.onConfigurationChanged(newConfig);
287
+        }
288
+    }
289
+
276
     @Override
290
     @Override
277
     public boolean onCreateOptionsMenu(Menu menu) {
291
     public boolean onCreateOptionsMenu(Menu menu) {
278
         mMenu = menu;
292
         mMenu = menu;
285
 
299
 
286
     @Override
300
     @Override
287
     public boolean onOptionsItemSelected(MenuItem item) {
301
     public boolean onOptionsItemSelected(MenuItem item) {
302
+        if (mDrawerToggle != null &&
303
+            getScreenStackSize() == 1 &&
304
+            mDrawerToggle.onOptionsItemSelected(item)) {
305
+            return true;
306
+        }
307
+
288
         if (item.getItemId() == android.R.id.home) {
308
         if (item.getItemId() == android.R.id.home) {
289
             onBackPressed();
309
             onBackPressed();
290
         } else {
310
         } else {
297
         return super.onOptionsItemSelected(item);
317
         return super.onOptionsItemSelected(item);
298
     }
318
     }
299
 
319
 
320
+    @Override
321
+    public void onPostCreate(Bundle savedInstanceState) {
322
+        super.onPostCreate(savedInstanceState);
323
+        if (mDrawerToggle != null) {
324
+            mDrawerToggle.syncState();
325
+        }
326
+    }
327
+
300
     public Menu getMenu() {
328
     public Menu getMenu() {
301
         return mMenu;
329
         return mMenu;
302
     }
330
     }
384
             mToolbar.showToolbar(animated);
412
             mToolbar.showToolbar(animated);
385
         }
413
         }
386
     }
414
     }
415
+
416
+    public void toggleDrawer(ReadableMap params) {
417
+        if (mToolbar == null || mDrawerToggle == null) {
418
+            return;
419
+        }
420
+
421
+        boolean animated = params.getBoolean(KEY_ANIMATED);
422
+        String side = params.getString(KEY_SIDE);
423
+        String to = params.getString(KEY_TO);
424
+        switch (to) {
425
+            case "open":
426
+                mToolbar.showDrawer(animated);
427
+                break;
428
+            case "closed":
429
+                mToolbar.hideDrawer(animated);
430
+                break;
431
+            default:
432
+                mToolbar.toggleDrawer(animated);
433
+                break;
434
+        }
435
+    }
387
 }
436
 }

+ 23
- 2
android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java View File

4
 import android.graphics.drawable.Drawable;
4
 import android.graphics.drawable.Drawable;
5
 import android.os.AsyncTask;
5
 import android.os.AsyncTask;
6
 import android.os.Bundle;
6
 import android.os.Bundle;
7
+import android.support.v4.widget.DrawerLayout;
7
 import android.view.Menu;
8
 import android.view.Menu;
8
 import android.widget.FrameLayout;
9
 import android.widget.FrameLayout;
9
 
10
 
12
 import com.facebook.react.bridge.ReadableMap;
13
 import com.facebook.react.bridge.ReadableMap;
13
 import com.reactnativenavigation.R;
14
 import com.reactnativenavigation.R;
14
 import com.reactnativenavigation.core.RctManager;
15
 import com.reactnativenavigation.core.RctManager;
16
+import com.reactnativenavigation.core.objects.Drawer;
15
 import com.reactnativenavigation.core.objects.Screen;
17
 import com.reactnativenavigation.core.objects.Screen;
16
 import com.reactnativenavigation.utils.StyleHelper;
18
 import com.reactnativenavigation.utils.StyleHelper;
17
 import com.reactnativenavigation.views.RnnToolBar;
19
 import com.reactnativenavigation.views.RnnToolBar;
25
  * Created by guyc on 02/04/16.
27
  * Created by guyc on 02/04/16.
26
  */
28
  */
27
 public class BottomTabActivity extends BaseReactActivity implements AHBottomNavigation.OnTabSelectedListener {
29
 public class BottomTabActivity extends BaseReactActivity implements AHBottomNavigation.OnTabSelectedListener {
30
+    public static final String DRAWER_PARAMS = "drawerParams";
28
     public static final String EXTRA_SCREENS = "extraScreens";
31
     public static final String EXTRA_SCREENS = "extraScreens";
29
 
32
 
30
     private static final String TAB_STYLE_BUTTON_COLOR = "tabBarButtonColor";
33
     private static final String TAB_STYLE_BUTTON_COLOR = "tabBarButtonColor";
40
     private AHBottomNavigation mBottomNavigation;
43
     private AHBottomNavigation mBottomNavigation;
41
     private FrameLayout mContentFrame;
44
     private FrameLayout mContentFrame;
42
     private ArrayList<ScreenStack> mScreenStacks;
45
     private ArrayList<ScreenStack> mScreenStacks;
46
+    private ScreenStack mDrawerStack;
47
+    private DrawerLayout mDrawerLayout;
43
     private int mCurrentStackPosition = -1;
48
     private int mCurrentStackPosition = -1;
44
 
49
 
45
     @Override
50
     @Override
52
         mContentFrame = (FrameLayout) findViewById(R.id.contentFrame);
57
         mContentFrame = (FrameLayout) findViewById(R.id.contentFrame);
53
 
58
 
54
         final ArrayList<Screen> screens = (ArrayList<Screen>) getIntent().getSerializableExtra(EXTRA_SCREENS);
59
         final ArrayList<Screen> screens = (ArrayList<Screen>) getIntent().getSerializableExtra(EXTRA_SCREENS);
60
+        final Drawer drawer = (Drawer) getIntent().getSerializableExtra(DRAWER_PARAMS);
55
         mBottomNavigation.setForceTint(true);
61
         mBottomNavigation.setForceTint(true);
62
+        setupDrawer(drawer, screens.get(0));
56
         setupTabs(getIntent().getExtras());
63
         setupTabs(getIntent().getExtras());
57
         setupPages(screens);
64
         setupPages(screens);
58
 
65
 
65
         });
72
         });
66
     }
73
     }
67
 
74
 
75
+    protected void setupDrawer(Drawer drawer, Screen screen) {
76
+        if (drawer == null || drawer.left == null) {
77
+            return;
78
+        }
79
+
80
+        mDrawerStack = new ScreenStack(this);
81
+        FrameLayout drawerFrame = (FrameLayout) findViewById(R.id.drawerFrame);
82
+        drawerFrame.addView(mDrawerStack);
83
+        mDrawerStack.push(drawer.left);
84
+
85
+        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
86
+        mDrawerToggle = mToolbar.setupDrawer(mDrawerLayout, drawer.left, screen);
87
+    }
88
+
68
     private void setupPages(ArrayList<Screen> screens) {
89
     private void setupPages(ArrayList<Screen> screens) {
69
         new SetupTabsTask(this, mToolbar, screens).execute();
90
         new SetupTabsTask(this, mToolbar, screens).execute();
70
     }
91
     }
189
 
210
 
190
         // Hide or show back button if needed
211
         // Hide or show back button if needed
191
         if (getScreenStackSize() > 1) {
212
         if (getScreenStackSize() > 1) {
192
-            mToolbar.showBackButton(getCurrentScreen());
213
+            mToolbar.setNavUpButton(getCurrentScreen());
193
         } else {
214
         } else {
194
-            mToolbar.hideBackButton();
215
+            mToolbar.setNavUpButton();
195
         }
216
         }
196
     }
217
     }
197
 
218
 

+ 23
- 0
android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java View File

1
 package com.reactnativenavigation.activities;
1
 package com.reactnativenavigation.activities;
2
 
2
 
3
+import android.support.v4.widget.DrawerLayout;
3
 import android.widget.FrameLayout;
4
 import android.widget.FrameLayout;
4
 
5
 
5
 import com.reactnativenavigation.R;
6
 import com.reactnativenavigation.R;
6
 import com.reactnativenavigation.core.RctManager;
7
 import com.reactnativenavigation.core.RctManager;
8
+import com.reactnativenavigation.core.objects.Drawer;
7
 import com.reactnativenavigation.core.objects.Screen;
9
 import com.reactnativenavigation.core.objects.Screen;
8
 import com.reactnativenavigation.utils.StyleHelper;
10
 import com.reactnativenavigation.utils.StyleHelper;
9
 import com.reactnativenavigation.views.RnnToolBar;
11
 import com.reactnativenavigation.views.RnnToolBar;
14
  */
16
  */
15
 public class SingleScreenActivity extends BaseReactActivity {
17
 public class SingleScreenActivity extends BaseReactActivity {
16
 
18
 
19
+    public static final String DRAWER_PARAMS = "drawerParams";
17
     public static final String EXTRA_SCREEN = "extraScreen";
20
     public static final String EXTRA_SCREEN = "extraScreen";
18
 
21
 
19
     private ScreenStack mScreenStack;
22
     private ScreenStack mScreenStack;
20
     private String mNavigatorId;
23
     private String mNavigatorId;
24
+    private ScreenStack mDrawerStack;
25
+    private DrawerLayout mDrawerLayout;
21
 
26
 
22
     @Override
27
     @Override
23
     protected void handleOnCreate() {
28
     protected void handleOnCreate() {
27
         mToolbar = (RnnToolBar) findViewById(R.id.toolbar);
32
         mToolbar = (RnnToolBar) findViewById(R.id.toolbar);
28
 
33
 
29
         final Screen screen = (Screen) getIntent().getSerializableExtra(EXTRA_SCREEN);
34
         final Screen screen = (Screen) getIntent().getSerializableExtra(EXTRA_SCREEN);
35
+        final Drawer drawer = (Drawer) getIntent().getSerializableExtra(DRAWER_PARAMS);
36
+
30
         mNavigatorId = screen.navigatorId;
37
         mNavigatorId = screen.navigatorId;
38
+        setupToolbar(screen);
39
+        setupDrawer(drawer, screen);
31
 
40
 
32
         mScreenStack = new ScreenStack(this);
41
         mScreenStack = new ScreenStack(this);
33
         FrameLayout contentFrame = (FrameLayout) findViewById(R.id.contentFrame);
42
         FrameLayout contentFrame = (FrameLayout) findViewById(R.id.contentFrame);
44
         });
53
         });
45
     }
54
     }
46
 
55
 
56
+    protected void setupDrawer(Drawer drawer, Screen screen) {
57
+        if (drawer == null || drawer.left == null) {
58
+            return;
59
+        }
60
+
61
+        mDrawerStack = new ScreenStack(this);
62
+        FrameLayout drawerFrame = (FrameLayout) findViewById(R.id.drawerFrame);
63
+        drawerFrame.addView(mDrawerStack);
64
+        mDrawerStack.push(drawer.left);
65
+
66
+        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
67
+        mDrawerToggle = mToolbar.setupDrawer(mDrawerLayout, drawer.left, screen);
68
+    }
69
+
47
     protected void setupToolbar(Screen screen) {
70
     protected void setupToolbar(Screen screen) {
48
         mToolbar.update(screen);
71
         mToolbar.update(screen);
49
         StyleHelper.updateStyles(mToolbar, screen);
72
         StyleHelper.updateStyles(mToolbar, screen);

+ 23
- 0
android/app/src/main/java/com/reactnativenavigation/core/objects/Drawer.java View File

1
+package com.reactnativenavigation.core.objects;
2
+
3
+import com.facebook.react.bridge.ReadableMap;
4
+
5
+import java.io.Serializable;
6
+
7
+public class Drawer extends JsonObject implements Serializable {
8
+    private static final long serialVersionUID = 982836768712398756L;
9
+
10
+    private static final String KEY_LEFT = "left";
11
+    private static final String KEY_RIGHT = "right";
12
+    private static final String KEY_DISABLE_OPEN_GESTURE = "disableOpenGesture";
13
+
14
+    public final Screen left;
15
+    public final Screen right;
16
+    public final boolean disableOpenGesture;
17
+
18
+    public Drawer(ReadableMap params) {
19
+        left = params.hasKey(KEY_LEFT) ? new Screen(params.getMap(KEY_LEFT)) : null;
20
+        right = params.hasKey(KEY_RIGHT) ? new Screen(params.getMap(KEY_RIGHT)) : null;
21
+        disableOpenGesture = getBoolean(params, KEY_DISABLE_OPEN_GESTURE);
22
+    }
23
+}

+ 6
- 2
android/app/src/main/java/com/reactnativenavigation/core/objects/Screen.java View File

34
     private static final String KEY_RIGHT_BUTTONS = "rightButtons";
34
     private static final String KEY_RIGHT_BUTTONS = "rightButtons";
35
     private static final String KEY_TOOL_BAR_STYLE = "navigatorStyle";
35
     private static final String KEY_TOOL_BAR_STYLE = "navigatorStyle";
36
     private static final String KEY_STATUS_BAR_COLOR = "statusBarColor";
36
     private static final String KEY_STATUS_BAR_COLOR = "statusBarColor";
37
-    private static final String KEY_TOOL_BAR_COLOR = "toolBarColor";
37
+    private static final String KEY_TOOL_BAR_COLOR = "navBarBackgroundColor";
38
     private static final String KEY_TOOL_BAR_HIDDEN = "navBarHidden";
38
     private static final String KEY_TOOL_BAR_HIDDEN = "navBarHidden";
39
     private static final String KEY_NAVIGATION_BAR_COLOR = "navigationBarColor";
39
     private static final String KEY_NAVIGATION_BAR_COLOR = "navigationBarColor";
40
     private static final String KEY_NAV_BAR_BUTTON_COLOR = "navBarButtonColor";
40
     private static final String KEY_NAV_BAR_BUTTON_COLOR = "navBarButtonColor";
44
     private static final String KEY_TAB_INDICATOR_COLOR = "tabIndicatorColor";
44
     private static final String KEY_TAB_INDICATOR_COLOR = "tabIndicatorColor";
45
     private static final String KEY_PROPS = "passProps";
45
     private static final String KEY_PROPS = "passProps";
46
 
46
 
47
-    public final String title;
47
+    public String title;
48
     public final String label;
48
     public final String label;
49
     public final String screenId;
49
     public final String screenId;
50
     public final String screenInstanceId;
50
     public final String screenInstanceId;
85
         setToolbarStyle(screen);
85
         setToolbarStyle(screen);
86
     }
86
     }
87
 
87
 
88
+    public void setTitle(ReadableMap params) {
89
+        this.title = getString(params, KEY_TITLE);
90
+    }
91
+
88
     public void setButtons(ReadableMap params) {
92
     public void setButtons(ReadableMap params) {
89
         this.buttons = getButtons(params);
93
         this.buttons = getButtons(params);
90
     }
94
     }

+ 23
- 2
android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java View File

15
 import com.reactnativenavigation.activities.RootActivity;
15
 import com.reactnativenavigation.activities.RootActivity;
16
 import com.reactnativenavigation.activities.SingleScreenActivity;
16
 import com.reactnativenavigation.activities.SingleScreenActivity;
17
 import com.reactnativenavigation.controllers.ModalController;
17
 import com.reactnativenavigation.controllers.ModalController;
18
+import com.reactnativenavigation.core.objects.Drawer;
18
 import com.reactnativenavigation.core.objects.Screen;
19
 import com.reactnativenavigation.core.objects.Screen;
19
 import com.reactnativenavigation.modal.RnnModal;
20
 import com.reactnativenavigation.modal.RnnModal;
20
 import com.reactnativenavigation.utils.BridgeUtils;
21
 import com.reactnativenavigation.utils.BridgeUtils;
39
     }
40
     }
40
 
41
 
41
     @ReactMethod
42
     @ReactMethod
42
-    public void startTabBasedApp(ReadableArray screens, ReadableMap style) {
43
+    public void startTabBasedApp(ReadableArray screens, ReadableMap style, ReadableMap drawerParams) {
43
         Activity context = ContextProvider.getActivityContext();
44
         Activity context = ContextProvider.getActivityContext();
44
         if (context != null && !context.isFinishing()) {
45
         if (context != null && !context.isFinishing()) {
45
             Intent intent = new Intent(context, BottomTabActivity.class);
46
             Intent intent = new Intent(context, BottomTabActivity.class);
47
 
48
 
48
             Bundle extras = new Bundle();
49
             Bundle extras = new Bundle();
49
             extras.putSerializable(BottomTabActivity.EXTRA_SCREENS, createScreens(screens));
50
             extras.putSerializable(BottomTabActivity.EXTRA_SCREENS, createScreens(screens));
51
+            if (drawerParams != null) {
52
+                extras.putSerializable(BottomTabActivity.DRAWER_PARAMS, new Drawer(drawerParams));
53
+            }
50
             if (style != null) {
54
             if (style != null) {
51
                 BridgeUtils.addMapToBundle(((ReadableNativeMap) style).toHashMap(), extras);
55
                 BridgeUtils.addMapToBundle(((ReadableNativeMap) style).toHashMap(), extras);
52
             }
56
             }
72
     }
76
     }
73
 
77
 
74
     @ReactMethod
78
     @ReactMethod
75
-    public void startSingleScreenApp(ReadableMap screen) {
79
+    public void startSingleScreenApp(ReadableMap screen, ReadableMap drawerParams) {
76
         BaseReactActivity context = ContextProvider.getActivityContext();
80
         BaseReactActivity context = ContextProvider.getActivityContext();
77
         if (context != null && !context.isFinishing()) {
81
         if (context != null && !context.isFinishing()) {
78
             Intent intent = new Intent(context, SingleScreenActivity.class);
82
             Intent intent = new Intent(context, SingleScreenActivity.class);
80
 
84
 
81
             Bundle extras = new Bundle();
85
             Bundle extras = new Bundle();
82
             extras.putSerializable(SingleScreenActivity.EXTRA_SCREEN, new Screen(screen));
86
             extras.putSerializable(SingleScreenActivity.EXTRA_SCREEN, new Screen(screen));
87
+            if (drawerParams != null) {
88
+                extras.putSerializable(SingleScreenActivity.DRAWER_PARAMS, new Drawer(drawerParams));
89
+            }
83
             intent.putExtras(extras);
90
             intent.putExtras(extras);
84
 
91
 
85
             context.startActivity(intent);
92
             context.startActivity(intent);
148
         });
155
         });
149
     }
156
     }
150
 
157
 
158
+    @ReactMethod
159
+    public void toggleDrawer(final ReadableMap params) {
160
+        final BaseReactActivity context = ContextProvider.getActivityContext();
161
+        if (context == null || context.isFinishing()) {
162
+            return;
163
+        }
164
+        context.runOnUiThread(new Runnable() {
165
+            @Override
166
+            public void run() {
167
+                context.toggleDrawer(params);
168
+            }
169
+        });
170
+    }
171
+
151
     @ReactMethod
172
     @ReactMethod
152
     public void toggleNavigationBar(final ReadableMap params) {
173
     public void toggleNavigationBar(final ReadableMap params) {
153
         final BaseReactActivity context = ContextProvider.getActivityContext();
174
         final BaseReactActivity context = ContextProvider.getActivityContext();

+ 139
- 19
android/app/src/main/java/com/reactnativenavigation/views/RnnToolBar.java View File

12
 import android.support.annotation.UiThread;
12
 import android.support.annotation.UiThread;
13
 import android.support.v4.content.ContextCompat;
13
 import android.support.v4.content.ContextCompat;
14
 import android.support.v4.content.res.ResourcesCompat;
14
 import android.support.v4.content.res.ResourcesCompat;
15
+import android.support.v4.widget.DrawerLayout;
15
 import android.support.v7.app.ActionBar;
16
 import android.support.v7.app.ActionBar;
17
+import android.support.v7.app.ActionBarDrawerToggle;
16
 import android.support.v7.app.AppCompatActivity;
18
 import android.support.v7.app.AppCompatActivity;
19
+import android.support.v7.graphics.drawable.DrawerArrowDrawable;
17
 import android.support.v7.widget.Toolbar;
20
 import android.support.v7.widget.Toolbar;
18
 import android.util.AttributeSet;
21
 import android.util.AttributeSet;
22
+import android.view.Gravity;
19
 import android.view.Menu;
23
 import android.view.Menu;
20
 import android.view.MenuItem;
24
 import android.view.MenuItem;
21
 import android.view.View;
25
 import android.view.View;
27
 import com.reactnativenavigation.core.objects.Button;
31
 import com.reactnativenavigation.core.objects.Button;
28
 import com.reactnativenavigation.core.objects.Screen;
32
 import com.reactnativenavigation.core.objects.Screen;
29
 import com.reactnativenavigation.utils.ContextProvider;
33
 import com.reactnativenavigation.utils.ContextProvider;
34
+import com.reactnativenavigation.utils.IconUtils;
30
 import com.reactnativenavigation.utils.ImageUtils;
35
 import com.reactnativenavigation.utils.ImageUtils;
31
 
36
 
32
 import java.lang.ref.WeakReference;
37
 import java.lang.ref.WeakReference;
43
     private static final int ANIMATE_DURATION = 180;
48
     private static final int ANIMATE_DURATION = 180;
44
 
49
 
45
     private List<Screen> mScreens;
50
     private List<Screen> mScreens;
51
+    private AsyncTask mDrawerIconTask;
46
     private AsyncTask mSetupToolbarTask;
52
     private AsyncTask mSetupToolbarTask;
47
     private Drawable mBackground;
53
     private Drawable mBackground;
54
+    private Drawable mDrawerIcon;
55
+    private Screen mDrawerScreen;
56
+    private DrawerLayout mDrawerLayout;
57
+    private ActionBarDrawerToggle mDrawerToggle;
48
     private ArrayList<View> mMenuItems;
58
     private ArrayList<View> mMenuItems;
49
 
59
 
50
     public RnnToolBar(Context context) {
60
     public RnnToolBar(Context context) {
105
         }
115
         }
106
     }
116
     }
107
 
117
 
118
+    public ActionBarDrawerToggle setupDrawer(DrawerLayout drawerLayout, Screen drawerScreen, Screen screen) {
119
+        if (drawerLayout == null || drawerScreen == null) {
120
+            return null;
121
+        }
122
+
123
+        mDrawerLayout = drawerLayout;
124
+        mDrawerScreen = drawerScreen;
125
+        mDrawerToggle = new ActionBarDrawerToggle(
126
+            ContextProvider.getActivityContext(),
127
+            mDrawerLayout,
128
+            this,
129
+            R.string.drawer_open,
130
+            R.string.drawer_close
131
+        );
132
+        mDrawerLayout.setDrawerListener(mDrawerToggle);
133
+        setupDrawerIconAsync(drawerScreen.icon, screen);
134
+
135
+        return mDrawerToggle;
136
+    }
137
+
138
+    public void setDrawerIcon(Drawable icon) {
139
+        mDrawerIcon = icon;
140
+    }
141
+
142
+    public void showDrawer(boolean animated) {
143
+        if (mDrawerLayout == null) {
144
+            return;
145
+        }
146
+
147
+        mDrawerLayout.openDrawer(Gravity.LEFT);
148
+    }
149
+
150
+    public void hideDrawer(boolean animated) {
151
+        if (mDrawerLayout == null) {
152
+            return;
153
+        }
154
+
155
+        mDrawerLayout.closeDrawer(Gravity.LEFT);
156
+    }
157
+
158
+    public void toggleDrawer(boolean animated) {
159
+        if (mDrawerLayout == null) {
160
+            return;
161
+        }
162
+
163
+        boolean visible = mDrawerLayout.isDrawerOpen(Gravity.LEFT);
164
+        if (visible) {
165
+            hideDrawer(animated);
166
+        } else {
167
+            showDrawer(animated);
168
+        }
169
+    }
170
+
171
+    public void setupDrawerIconAsync(String drawerIconSource, Screen screen) {
172
+        if (mDrawerIconTask == null) {
173
+            mDrawerIconTask = new SetupDrawerIconTask(this, drawerIconSource, screen).execute();
174
+        }
175
+    }
176
+
108
     public void setupToolbarButtonsAsync(Screen newScreen) {
177
     public void setupToolbarButtonsAsync(Screen newScreen) {
109
         if (newScreen != null) {
178
         if (newScreen != null) {
110
             this.setupToolbarButtonsAsync(null, newScreen);
179
             this.setupToolbarButtonsAsync(null, newScreen);
144
         hideToolbar(false);
213
         hideToolbar(false);
145
     }
214
     }
146
 
215
 
147
-    @SuppressWarnings({"ConstantConditions"})
148
-    public void showBackButton(Screen screen) {
149
-        ActionBar actionBar = ContextProvider.getActivityContext().getSupportActionBar();
150
-        Drawable backButton = setupBackButton(screen);
151
-        actionBar.setHomeAsUpIndicator(backButton);
152
-        actionBar.setDisplayHomeAsUpEnabled(true);
216
+    public void setNavUpButton() {
217
+        setNavUpButton(null);
153
     }
218
     }
154
 
219
 
155
-    @SuppressLint("PrivateResource")
156
     @SuppressWarnings({"ConstantConditions"})
220
     @SuppressWarnings({"ConstantConditions"})
157
-    private Drawable setupBackButton(Screen screen) {
158
-        Resources resources = getResources();
159
-        final Drawable backButton = ResourcesCompat.getDrawable(resources,
160
-                R.drawable.abc_ic_ab_back_mtrl_am_alpha,
161
-                ContextProvider.getActivityContext().getTheme());
162
-        int tintColor = screen.navBarButtonColor != null ? screen.navBarButtonColor : Color.BLACK;
163
-        ImageUtils.tint(backButton, tintColor);
164
-        return backButton;
165
-    }
221
+    public void setNavUpButton(Screen screen) {
222
+        ActionBar actionBar = ContextProvider.getActivityContext().getSupportActionBar();
223
+        if (actionBar == null) {
224
+            return;
225
+        }
166
 
226
 
167
-    @SuppressWarnings({"ConstantConditions"})
168
-    public void hideBackButton() {
169
-        ContextProvider.getActivityContext().getSupportActionBar().setDisplayHomeAsUpEnabled(false);
227
+        boolean isBack = screen != null;
228
+        boolean hasDrawer = mDrawerToggle != null;
229
+
230
+        Drawable navIcon = null;
231
+        DrawerArrowDrawable navArrow = null;
232
+        if (hasDrawer && mDrawerIcon == null) {
233
+            navArrow = (DrawerArrowDrawable) this.getNavigationIcon();
234
+        } else {
235
+            if (isBack) {
236
+                navArrow = new DrawerArrowDrawable(ContextProvider.getActivityContext());
237
+            } else if (hasDrawer) {
238
+                navIcon = mDrawerIcon;
239
+            }
240
+        }
241
+
242
+        if (navArrow != null) {
243
+            navArrow.setProgress(isBack ? 1.0f : 0.0f);
244
+            if (screen.navBarButtonColor != null) {
245
+                navArrow.setColor(screen.navBarButtonColor);
246
+            } else {
247
+                navArrow.setColor(Color.BLACK);
248
+            }
249
+            navIcon = navArrow;
250
+        }
251
+
252
+        actionBar.setHomeAsUpIndicator(navIcon);
253
+        actionBar.setDisplayHomeAsUpEnabled(navIcon != null);
170
     }
254
     }
171
 
255
 
172
     /**
256
     /**
186
         setupToolbarButtonsAsync(screen);
270
         setupToolbarButtonsAsync(screen);
187
     }
271
     }
188
 
272
 
273
+    private static class SetupDrawerIconTask extends AsyncTask<Void, Void, Drawable> {
274
+        private final WeakReference<RnnToolBar> mToolbarWR;
275
+        private final String mDrawerIconSource;
276
+        private final Integer mTintColor;
277
+
278
+        public SetupDrawerIconTask(RnnToolBar toolBar, String drawerIconSource, Screen screen) {
279
+            mToolbarWR = new WeakReference<>(toolBar);
280
+            mDrawerIconSource = drawerIconSource;
281
+            mTintColor = screen.navBarButtonColor;
282
+        }
283
+
284
+        @Override
285
+        protected Drawable doInBackground(Void... params) {
286
+            Context context = ContextProvider.getActivityContext();
287
+            if (context == null || mDrawerIconSource == null) {
288
+                return null;
289
+            }
290
+
291
+            return IconUtils.getIcon(context, mDrawerIconSource);
292
+        }
293
+
294
+        @Override
295
+        protected void onPostExecute(Drawable drawerIcon) {
296
+            RnnToolBar toolBar = mToolbarWR.get();
297
+            if (drawerIcon != null) {
298
+                if (mTintColor != null) {
299
+                    ImageUtils.tint(drawerIcon, mTintColor);
300
+                }
301
+                toolBar.setDrawerIcon(drawerIcon);
302
+            }
303
+
304
+            toolBar.setNavUpButton();
305
+            mToolbarWR.clear();
306
+        }
307
+    }
308
+
189
     private static class SetupToolbarButtonsTask extends AsyncTask<Void, Void, Map<String, Drawable>> {
309
     private static class SetupToolbarButtonsTask extends AsyncTask<Void, Void, Map<String, Drawable>> {
190
         private final List<Button> mOldButtons;
310
         private final List<Button> mOldButtons;
191
         private final List<Button> mNewButtons;
311
         private final List<Button> mNewButtons;

+ 14
- 3
android/app/src/main/res/layout/bottom_tab_activity.xml View File

20
             app:layout_scrollFlags="scroll|enterAlways"/>
20
             app:layout_scrollFlags="scroll|enterAlways"/>
21
     </android.support.design.widget.AppBarLayout>
21
     </android.support.design.widget.AppBarLayout>
22
 
22
 
23
-    <FrameLayout
24
-        android:id="@+id/contentFrame"
23
+    <android.support.v4.widget.DrawerLayout
24
+        xmlns:android="http://schemas.android.com/apk/res/android"
25
+        android:id="@+id/drawerLayout"
25
         android:layout_width="match_parent"
26
         android:layout_width="match_parent"
26
         android:layout_height="0dp"
27
         android:layout_height="0dp"
27
-        android:layout_weight="1"/>
28
+        android:layout_weight="1">
29
+        <FrameLayout
30
+            android:id="@+id/contentFrame"
31
+            android:layout_width="match_parent"
32
+            android:layout_height="0dp"
33
+            android:layout_weight="1"/>
34
+        <FrameLayout android:id="@+id/drawerFrame"
35
+            android:layout_width="240dp"
36
+            android:layout_height="match_parent"
37
+            android:layout_gravity="start"/>
38
+    </android.support.v4.widget.DrawerLayout>
28
 
39
 
29
     <com.aurelhubert.ahbottomnavigation.AHBottomNavigation
40
     <com.aurelhubert.ahbottomnavigation.AHBottomNavigation
30
         android:id="@+id/bottom_tab_bar"
41
         android:id="@+id/bottom_tab_bar"

+ 13
- 3
android/app/src/main/res/layout/single_screen_activity.xml View File

17
             app:layout_scrollFlags="scroll|enterAlways"/>
17
             app:layout_scrollFlags="scroll|enterAlways"/>
18
     </android.support.design.widget.AppBarLayout>
18
     </android.support.design.widget.AppBarLayout>
19
 
19
 
20
-    <FrameLayout
21
-        android:id="@+id/contentFrame"
20
+    <android.support.v4.widget.DrawerLayout
21
+        xmlns:android="http://schemas.android.com/apk/res/android"
22
+        android:id="@+id/drawerLayout"
22
         android:layout_width="match_parent"
23
         android:layout_width="match_parent"
23
-        android:layout_height="match_parent"/>
24
+        android:layout_height="match_parent">
25
+        <FrameLayout
26
+            android:id="@+id/contentFrame"
27
+            android:layout_width="match_parent"
28
+            android:layout_height="match_parent"/>
29
+        <FrameLayout android:id="@+id/drawerFrame"
30
+            android:layout_width="240dp"
31
+            android:layout_height="match_parent"
32
+            android:layout_gravity="start"/>
33
+    </android.support.v4.widget.DrawerLayout>
24
 </LinearLayout>
34
 </LinearLayout>

+ 5
- 0
android/app/src/main/res/values/strings.xml View File

1
+<?xml version="1.0" encoding="utf-8"?>
2
+<resources>
3
+    <string name="drawer_close">Drawer Close</string>
4
+    <string name="drawer_open">Drawer Open</string>
5
+</resources>

+ 31
- 2
src/platformSpecific.android.js View File

19
   addNavigatorButtons(screen);
19
   addNavigatorButtons(screen);
20
   addNavigationStyleParams(screen);
20
   addNavigationStyleParams(screen);
21
   screen.passProps = params.passProps;
21
   screen.passProps = params.passProps;
22
-  RctActivity.startSingleScreenApp(screen);
22
+  const drawer = setupDrawer(params.drawer);
23
+  RctActivity.startSingleScreenApp(screen, drawer);
23
 }
24
 }
24
 
25
 
25
 function startTabBasedApp(params) {
26
 function startTabBasedApp(params) {
41
     tab.passProps = params.passProps;
42
     tab.passProps = params.passProps;
42
   });
43
   });
43
 
44
 
44
-  RctActivity.startTabBasedApp(params.tabs, params.tabsStyle);
45
+  const drawer = setupDrawer(params.drawer);
46
+  RctActivity.startTabBasedApp(params.tabs, params.tabsStyle, drawer);
45
 }
47
 }
46
 
48
 
47
 function navigatorPush(navigator, params) {
49
 function navigatorPush(navigator, params) {
101
   });
103
   });
102
 }
104
 }
103
 
105
 
106
+function navigatorToggleDrawer(navigator, params) {
107
+  RctActivity.toggleDrawer({
108
+    side: params.side,
109
+    animated: !(params.animated === false),
110
+    to: params.to || ''
111
+  });
112
+}
113
+
104
 function navigatorToggleNavBar(navigator, params) {
114
 function navigatorToggleNavBar(navigator, params) {
105
   RctActivity.toggleNavigationBar({
115
   RctActivity.toggleNavigationBar({
106
     hidden: params.to === 'hidden',
116
     hidden: params.to === 'hidden',
160
   screen.navigatorStyle = Screen.navigatorStyle;
170
   screen.navigatorStyle = Screen.navigatorStyle;
161
 }
171
 }
162
 
172
 
173
+function setupDrawer(drawerParams) {
174
+  const drawer = Object.assign({}, drawerParams);
175
+  [drawer.left, drawer.right].forEach(side => {
176
+    if (!side) {
177
+      return;
178
+    }
179
+    const icon = resolveAssetSource(side.icon);
180
+    if (icon) {
181
+      side.icon = icon.uri;
182
+    }
183
+  });
184
+  if (drawer.disableOpenGesture === undefined) {
185
+    drawer.disableOpenGesture = false;
186
+  };
187
+
188
+  return drawer;
189
+}
190
+
163
 export default {
191
 export default {
164
   startTabBasedApp,
192
   startTabBasedApp,
165
   startSingleScreenApp,
193
   startSingleScreenApp,
174
   navigatorSetTabBadge,
202
   navigatorSetTabBadge,
175
   navigatorSetTitle,
203
   navigatorSetTitle,
176
   navigatorSwitchToTab,
204
   navigatorSwitchToTab,
205
+  navigatorToggleDrawer,
177
   navigatorToggleTabs,
206
   navigatorToggleTabs,
178
   navigatorToggleNavBar
207
   navigatorToggleNavBar
179
 }
208
 }