Browse Source

Merge pull request #82 from the-mx-group/android_drawer

Android drawer implementation
Guy Carmeli 8 years ago
parent
commit
be2bc55209

+ 73
- 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.v4.widget.DrawerLayout;
11
+import android.support.v7.app.ActionBarDrawerToggle;
9
 import android.support.v7.app.AppCompatActivity;
12
 import android.support.v7.app.AppCompatActivity;
10
 import android.util.Log;
13
 import android.util.Log;
11
 import android.view.KeyEvent;
14
 import android.view.KeyEvent;
12
 import android.view.Menu;
15
 import android.view.Menu;
13
 import android.view.MenuItem;
16
 import android.view.MenuItem;
14
 import android.widget.EditText;
17
 import android.widget.EditText;
18
+import android.widget.FrameLayout;
15
 import android.widget.Toast;
19
 import android.widget.Toast;
16
 
20
 
17
 import com.facebook.common.logging.FLog;
21
 import com.facebook.common.logging.FLog;
28
 import com.reactnativenavigation.controllers.ModalController;
32
 import com.reactnativenavigation.controllers.ModalController;
29
 import com.reactnativenavigation.core.RctManager;
33
 import com.reactnativenavigation.core.RctManager;
30
 import com.reactnativenavigation.core.objects.Button;
34
 import com.reactnativenavigation.core.objects.Button;
35
+import com.reactnativenavigation.core.objects.Drawer;
31
 import com.reactnativenavigation.core.objects.Screen;
36
 import com.reactnativenavigation.core.objects.Screen;
32
 import com.reactnativenavigation.modal.RnnModal;
37
 import com.reactnativenavigation.modal.RnnModal;
33
 import com.reactnativenavigation.packages.RnnPackage;
38
 import com.reactnativenavigation.packages.RnnPackage;
34
 import com.reactnativenavigation.utils.ContextProvider;
39
 import com.reactnativenavigation.utils.ContextProvider;
35
 import com.reactnativenavigation.utils.StyleHelper;
40
 import com.reactnativenavigation.utils.StyleHelper;
36
 import com.reactnativenavigation.views.RnnToolBar;
41
 import com.reactnativenavigation.views.RnnToolBar;
42
+import com.reactnativenavigation.views.ScreenStack;
37
 
43
 
38
 import java.util.Arrays;
44
 import java.util.Arrays;
39
 import java.util.List;
45
 import java.util.List;
48
     protected static final String KEY_ANIMATED = "animated";
54
     protected static final String KEY_ANIMATED = "animated";
49
     protected static final String KEY_BADGE = "badge";
55
     protected static final String KEY_BADGE = "badge";
50
     protected static final String KEY_HIDDEN = "hidden";
56
     protected static final String KEY_HIDDEN = "hidden";
57
+    protected static final String KEY_SIDE = "side";
51
     protected static final String KEY_TAB_INDEX = "tabIndex";
58
     protected static final String KEY_TAB_INDEX = "tabIndex";
52
     protected static final String KEY_TITLE = "title";
59
     protected static final String KEY_TITLE = "title";
60
+    protected static final String KEY_TO = "to";
53
     private static final String TAG = "BaseReactActivity";
61
     private static final String TAG = "BaseReactActivity";
54
     private static final String REDBOX_PERMISSION_MESSAGE =
62
     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";
63
             "Overlay permissions needs to be granted in order for react native apps to run in dev mode";
59
     private boolean mDoRefresh = false;
67
     private boolean mDoRefresh = false;
60
     private Menu mMenu;
68
     private Menu mMenu;
61
     protected RnnToolBar mToolbar;
69
     protected RnnToolBar mToolbar;
70
+    protected ActionBarDrawerToggle mDrawerToggle;
71
+    protected DrawerLayout mDrawerLayout;
72
+    protected ScreenStack mDrawerStack;
62
 
73
 
63
     /**
74
     /**
64
      * Returns the name of the bundle in assets. If this is null, and no file path is specified for
75
      * Returns the name of the bundle in assets. If this is null, and no file path is specified for
223
 
234
 
224
             if (getCurrentNavigatorId().equals(screen.navigatorId) &&
235
             if (getCurrentNavigatorId().equals(screen.navigatorId) &&
225
                 getScreenStackSize() >= 1) {
236
                 getScreenStackSize() >= 1) {
226
-                mToolbar.showBackButton(screen);
237
+                mToolbar.setNavUpButton(screen);
227
             }
238
             }
228
         }
239
         }
229
     }
240
     }
233
         if (mToolbar != null &&
244
         if (mToolbar != null &&
234
             getCurrentNavigatorId().equals(navigatorId) &&
245
             getCurrentNavigatorId().equals(navigatorId) &&
235
             getScreenStackSize() <= 2) {
246
             getScreenStackSize() <= 2) {
236
-            mToolbar.hideBackButton();
247
+            mToolbar.setNavUpButton();
237
         }
248
         }
249
+
238
         return null;
250
         return null;
239
     }
251
     }
240
 
252
 
241
     @CallSuper
253
     @CallSuper
242
     public Screen popToRoot(String navigatorId) {
254
     public Screen popToRoot(String navigatorId) {
243
         if (mToolbar != null) {
255
         if (mToolbar != null) {
244
-            mToolbar.hideBackButton();
256
+            mToolbar.setNavUpButton();
245
         }
257
         }
246
 
258
 
247
         return null;
259
         return null;
251
     public Screen resetTo(Screen screen) {
263
     public Screen resetTo(Screen screen) {
252
         StyleHelper.updateStyles(mToolbar, screen);
264
         StyleHelper.updateStyles(mToolbar, screen);
253
         if (mToolbar != null) {
265
         if (mToolbar != null) {
254
-            mToolbar.hideBackButton();
266
+            mToolbar.setNavUpButton();
255
         }
267
         }
256
 
268
 
257
         return null;
269
         return null;
273
 
285
 
274
     public abstract int getScreenStackSize();
286
     public abstract int getScreenStackSize();
275
 
287
 
288
+    @Override
289
+    public void onConfigurationChanged(Configuration newConfig) {
290
+        super.onConfigurationChanged(newConfig);
291
+        if (mDrawerToggle != null) {
292
+            mDrawerToggle.onConfigurationChanged(newConfig);
293
+        }
294
+    }
295
+
276
     @Override
296
     @Override
277
     public boolean onCreateOptionsMenu(Menu menu) {
297
     public boolean onCreateOptionsMenu(Menu menu) {
278
         mMenu = menu;
298
         mMenu = menu;
285
 
305
 
286
     @Override
306
     @Override
287
     public boolean onOptionsItemSelected(MenuItem item) {
307
     public boolean onOptionsItemSelected(MenuItem item) {
308
+        if (mDrawerToggle != null &&
309
+            getScreenStackSize() == 1 &&
310
+            mDrawerToggle.onOptionsItemSelected(item)) {
311
+            return true;
312
+        }
313
+
288
         if (item.getItemId() == android.R.id.home) {
314
         if (item.getItemId() == android.R.id.home) {
289
             onBackPressed();
315
             onBackPressed();
290
         } else {
316
         } else {
297
         return super.onOptionsItemSelected(item);
323
         return super.onOptionsItemSelected(item);
298
     }
324
     }
299
 
325
 
326
+    @Override
327
+    public void onPostCreate(Bundle savedInstanceState) {
328
+        super.onPostCreate(savedInstanceState);
329
+        if (mDrawerToggle != null) {
330
+            mDrawerToggle.syncState();
331
+        }
332
+    }
333
+
300
     public Menu getMenu() {
334
     public Menu getMenu() {
301
         return mMenu;
335
         return mMenu;
302
     }
336
     }
355
         super.onBackPressed();
389
         super.onBackPressed();
356
     }
390
     }
357
 
391
 
392
+    protected void setupDrawer(Screen screen, Drawer drawer, int drawerFrameId, int drawerLayoutId) {
393
+        if (drawer == null || drawer.left == null) {
394
+            return;
395
+        }
396
+
397
+        mDrawerStack = new ScreenStack(this);
398
+        FrameLayout drawerFrame = (FrameLayout) findViewById(drawerFrameId);
399
+        drawerFrame.addView(mDrawerStack);
400
+        mDrawerStack.push(drawer.left);
401
+
402
+        mDrawerLayout = (DrawerLayout) findViewById(drawerLayoutId);
403
+        mDrawerToggle = mToolbar.setupDrawer(mDrawerLayout, drawer.left, screen);
404
+    }
405
+
358
     public void setNavigationButtons(ReadableMap buttons){
406
     public void setNavigationButtons(ReadableMap buttons){
359
         if (mToolbar == null) {
407
         if (mToolbar == null) {
360
             return;
408
             return;
384
             mToolbar.showToolbar(animated);
432
             mToolbar.showToolbar(animated);
385
         }
433
         }
386
     }
434
     }
435
+
436
+    public void toggleDrawer(ReadableMap params) {
437
+        if (mToolbar == null || mDrawerToggle == null) {
438
+            return;
439
+        }
440
+
441
+        boolean animated = params.getBoolean(KEY_ANIMATED);
442
+        String side = params.getString(KEY_SIDE);
443
+        String to = params.getString(KEY_TO);
444
+        switch (to) {
445
+            case "open":
446
+                mToolbar.showDrawer(animated);
447
+                break;
448
+            case "closed":
449
+                mToolbar.hideDrawer(animated);
450
+                break;
451
+            default:
452
+                mToolbar.toggleDrawer(animated);
453
+                break;
454
+        }
455
+    }
387
 }
456
 }

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

12
 import com.facebook.react.bridge.ReadableMap;
12
 import com.facebook.react.bridge.ReadableMap;
13
 import com.reactnativenavigation.R;
13
 import com.reactnativenavigation.R;
14
 import com.reactnativenavigation.core.RctManager;
14
 import com.reactnativenavigation.core.RctManager;
15
+import com.reactnativenavigation.core.objects.Drawer;
15
 import com.reactnativenavigation.core.objects.Screen;
16
 import com.reactnativenavigation.core.objects.Screen;
16
 import com.reactnativenavigation.utils.StyleHelper;
17
 import com.reactnativenavigation.utils.StyleHelper;
17
 import com.reactnativenavigation.views.RnnToolBar;
18
 import com.reactnativenavigation.views.RnnToolBar;
25
  * Created by guyc on 02/04/16.
26
  * Created by guyc on 02/04/16.
26
  */
27
  */
27
 public class BottomTabActivity extends BaseReactActivity implements AHBottomNavigation.OnTabSelectedListener {
28
 public class BottomTabActivity extends BaseReactActivity implements AHBottomNavigation.OnTabSelectedListener {
29
+    public static final String DRAWER_PARAMS = "drawerParams";
28
     public static final String EXTRA_SCREENS = "extraScreens";
30
     public static final String EXTRA_SCREENS = "extraScreens";
29
 
31
 
30
     private static final String TAB_STYLE_BUTTON_COLOR = "tabBarButtonColor";
32
     private static final String TAB_STYLE_BUTTON_COLOR = "tabBarButtonColor";
52
         mContentFrame = (FrameLayout) findViewById(R.id.contentFrame);
54
         mContentFrame = (FrameLayout) findViewById(R.id.contentFrame);
53
 
55
 
54
         final ArrayList<Screen> screens = (ArrayList<Screen>) getIntent().getSerializableExtra(EXTRA_SCREENS);
56
         final ArrayList<Screen> screens = (ArrayList<Screen>) getIntent().getSerializableExtra(EXTRA_SCREENS);
57
+        final Drawer drawer = (Drawer) getIntent().getSerializableExtra(DRAWER_PARAMS);
55
         mBottomNavigation.setForceTint(true);
58
         mBottomNavigation.setForceTint(true);
59
+        setupDrawer(screens.get(0), drawer, R.id.drawerFrame, R.id.drawerLayout);
56
         setupTabs(getIntent().getExtras());
60
         setupTabs(getIntent().getExtras());
57
         setupPages(screens);
61
         setupPages(screens);
58
 
62
 
190
 
194
 
191
         // Hide or show back button if needed
195
         // Hide or show back button if needed
192
         if (getScreenStackSize() > 1) {
196
         if (getScreenStackSize() > 1) {
193
-            mToolbar.showBackButton(getCurrentScreen());
197
+            mToolbar.setNavUpButton(getCurrentScreen());
194
         } else {
198
         } else {
195
-            mToolbar.hideBackButton();
199
+            mToolbar.setNavUpButton();
196
         }
200
         }
197
     }
201
     }
198
 
202
 

+ 7
- 1
android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java View File

4
 
4
 
5
 import com.reactnativenavigation.R;
5
 import com.reactnativenavigation.R;
6
 import com.reactnativenavigation.core.RctManager;
6
 import com.reactnativenavigation.core.RctManager;
7
+import com.reactnativenavigation.core.objects.Drawer;
7
 import com.reactnativenavigation.core.objects.Screen;
8
 import com.reactnativenavigation.core.objects.Screen;
8
 import com.reactnativenavigation.utils.StyleHelper;
9
 import com.reactnativenavigation.utils.StyleHelper;
9
 import com.reactnativenavigation.views.RnnToolBar;
10
 import com.reactnativenavigation.views.RnnToolBar;
14
  */
15
  */
15
 public class SingleScreenActivity extends BaseReactActivity {
16
 public class SingleScreenActivity extends BaseReactActivity {
16
 
17
 
18
+    public static final String DRAWER_PARAMS = "drawerParams";
17
     public static final String EXTRA_SCREEN = "extraScreen";
19
     public static final String EXTRA_SCREEN = "extraScreen";
18
 
20
 
19
     private ScreenStack mScreenStack;
21
     private ScreenStack mScreenStack;
27
         mToolbar = (RnnToolBar) findViewById(R.id.toolbar);
29
         mToolbar = (RnnToolBar) findViewById(R.id.toolbar);
28
 
30
 
29
         final Screen screen = (Screen) getIntent().getSerializableExtra(EXTRA_SCREEN);
31
         final Screen screen = (Screen) getIntent().getSerializableExtra(EXTRA_SCREEN);
32
+        final Drawer drawer = (Drawer) getIntent().getSerializableExtra(DRAWER_PARAMS);
33
+
30
         mNavigatorId = screen.navigatorId;
34
         mNavigatorId = screen.navigatorId;
35
+        setupToolbar(screen);
36
+        setupDrawer(screen, drawer, R.id.drawerFrame, R.id.drawerLayout);
31
 
37
 
32
         mScreenStack = new ScreenStack(this);
38
         mScreenStack = new ScreenStack(this);
33
         FrameLayout contentFrame = (FrameLayout) findViewById(R.id.contentFrame);
39
         FrameLayout contentFrame = (FrameLayout) findViewById(R.id.contentFrame);
48
         mToolbar.update(screen);
54
         mToolbar.update(screen);
49
         StyleHelper.updateStyles(mToolbar, screen);
55
         StyleHelper.updateStyles(mToolbar, screen);
50
     }
56
     }
51
-    
57
+
52
     @Override
58
     @Override
53
     public void push(Screen screen) {
59
     public void push(Screen screen) {
54
         super.push(screen);
60
         super.push(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 != null && 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 = Object.assign({}, screen.navigatorStyle, Screen.navigatorStyle);
170
   screen.navigatorStyle = Object.assign({}, 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
 }