├── .gitignore ├── Gruntfile.js ├── LICENSE ├── README.md ├── android ├── assets │ └── README ├── build.xml ├── dist │ ├── com.tripvi.drawerlayout-android-1.4.0.zip │ ├── com.tripvi.drawerlayout-android-1.4.2.zip │ ├── com.tripvi.drawerlayout-android-2.0.0.zip │ ├── com.tripvi.drawerlayout-android-3.0.0.zip │ ├── com.tripvi.drawerlayout-android-3.0.1.zip │ └── drawerlayout.jar ├── lib │ └── .gitkeep ├── manifest ├── platform │ ├── README │ └── android │ │ └── res │ │ ├── layout │ │ └── drawer_main.xml │ │ └── values │ │ └── strings.xml ├── src │ └── com │ │ └── tripvi │ │ └── drawerlayout │ │ ├── ContentFrame.java │ │ ├── Drawer.java │ │ ├── DrawerProxy.java │ │ └── DrawerlayoutModule.java └── timodule.xml ├── documentation └── index.md ├── example └── app.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | tmp 3 | bin 4 | build 5 | .apt_generated 6 | .project 7 | .classpath 8 | .settings 9 | libs 10 | build.properties 11 | *.apk 12 | .idea 13 | node_modules 14 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | 3 | module.exports = function(grunt) { 4 | 5 | grunt.registerTask('build', 'build the module', function() { 6 | 7 | var done = this.async(); 8 | 9 | // runt titanium script to build the module 10 | var ti = grunt.util.spawn({ 11 | cmd: 'ti', 12 | args: ['build', '-p', 'android', '--build-only'], 13 | opts: { 14 | cwd: 'android' 15 | } 16 | }, function(error, result, code) { 17 | if(error) { 18 | grunt.fail.warn(error, code); 19 | } else { 20 | grunt.log.ok('build successful'); 21 | } 22 | done(error, result); 23 | }); 24 | ti.stdout.on('data', grunt.log.write); 25 | ti.stderr.on('data', grunt.log.error); 26 | 27 | }); 28 | 29 | grunt.registerTask('deploy', 'install the module', function() { 30 | 31 | var done = this.async(); 32 | var version = grunt.file.readJSON('package.json').version; 33 | var modPath = path.join(__dirname, 'android/dist/com.tripvi.drawerlayout-android-'+version+'.zip'); 34 | 35 | var install = grunt.util.spawn({ 36 | cmd: 'gittio', 37 | args: ['install', '-g', modPath] 38 | }, function(error, result, code) { 39 | if(error) { 40 | grunt.fail.warn(error, code); 41 | } else { 42 | grunt.log.ok('installed'); 43 | } 44 | done(error, result); 45 | }); 46 | install.stdout.on('data', grunt.log.write); 47 | install.stderr.on('data', grunt.log.error); 48 | }); 49 | 50 | grunt.registerTask('version', 'update version from package.json', function() { 51 | 52 | // read files 53 | var version = grunt.file.readJSON('package.json').version; 54 | var manifest = grunt.file.read('android/manifest'); 55 | var readme = grunt.file.read('README.md'); 56 | 57 | // update manifest 58 | grunt.file.write('android/manifest', manifest.replace(/^version.*$/m, "version: " + version)); 59 | 60 | // update readme 61 | grunt.file.write('README.md', readme.replace(/gittio-[\d\.]{2,}-00B4CC\.svg/g, "gittio-" + version + "-00B4CC.svg")); 62 | 63 | }); 64 | 65 | grunt.registerTask('default', ['version', 'build', 'deploy']); 66 | 67 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2013 - 2014 Tripvi.Inc 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | 21 | 22 | Copyright (c) 2015 - 2016 Manuel Lehner 23 | 24 | Permission is hereby granted, free of charge, to any person obtaining a copy 25 | of this software and associated documentation files (the "Software"), to deal 26 | in the Software without restriction, including without limitation the rights 27 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 28 | copies of the Software, and to permit persons to whom the Software is 29 | furnished to do so, subject to the following conditions: 30 | 31 | The above copyright notice and this permission notice shall be included in 32 | all copies or substantial portions of the Software. 33 | 34 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 35 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 36 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 37 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 38 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 39 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 40 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ⚠️ 2 | 3 | *THIS REPO IS DEPRECATED SINCE THE DRAWER LAYOUT WAS INTEGRATED INTO THE TITANIUM CORE. CONSIDER USING: https://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.Android.DrawerLayout* 4 | 5 | ___ 6 | 7 | # DEPRECATED (Ti.DrawerLayout) [![gittio](http://img.shields.io/badge/gittio-3.0.1-00B4CC.svg)](http://gitt.io/component/com.tripvi.drawerlayout) [![No Maintenance Intended](http://unmaintained.tech/badge.svg)](http://unmaintained.tech/) 8 | Native Android [Navigation Drawer](http://developer.android.com/design/patterns/navigation-drawer.html) for [Titanium](http://www.appcelerator.com/titanium/) 9 | 10 | - [Overview](#overview) 11 | - [Installation](#installation) 12 | - [Usage](#usage) 13 | - [Docs](documentation/index.md) 14 | - [Demo](https://github.com/manumaticx/NavigationDrawer-Demo) 15 | - [License](#license) 16 | 17 | 18 | _This is a fork of [Tripvi/Ti.DrawerLayout](https://github.com/Tripvi/Ti.DrawerLayout)_ 19 | 20 | ## Overview 21 | 22 | 23 | 24 | This module adds support for using the [DrawerLayout](http://developer.android.com/reference/android/support/v4/widget/DrawerLayout.html) in Titanium Apps. 25 | 26 | The Drawer Layout is a view that can be pulled from the edge of a window. This can answer various purposes. The most common use case is the Navigation Drawer as seen in the above screenshot. The Navigation Drawer displays navigation options in a drawer which slides in from the left edge. 27 | 28 | To expand the drawer the user can either touch the app icon or swipe from the left edge. The navigation drawer overlays the content but not the action bar. 29 | 30 | ## Installation 31 | 32 | * Grab the latest package from the [dist](android/dist) folder 33 | * Install it following [this guide](http://docs.appcelerator.com/titanium/latest/#!/guide/Using_a_Module) 34 | * with [gittio](http://gitt.io/): `$ gittio install com.tripvi.drawerlayout` 35 | 36 | ## Usage 37 | 38 | Here's an example of how to use the module. 39 | 40 | > **Please note:** This module requires a Theme without ActionBar such as `Theme.AppCompat.Light.NoActionBar` since it adds a Toolbar to its own layout. If you do not want the Toolbar, just pass the `hideToolbar` property at creation-time. 41 | 42 | ```javascript 43 | // Load module 44 | var TiDrawerLayout = require('com.tripvi.drawerlayout'); 45 | 46 | // define left and center view 47 | var leftView = Ti.UI.createView({backgroundColor:'gray'}); 48 | var centerView = Ti.UI.createView({backgroundColor:'white'}); 49 | 50 | // create the Drawer 51 | var drawer = TiDrawerLayout.createDrawer({ 52 | leftView: leftView, 53 | centerView: centerView 54 | }); 55 | 56 | // create a window 57 | var win = Ti.UI.createWindow(); 58 | 59 | // add the drawer to the window 60 | win.add(drawer); 61 | 62 | // listen for the open event... 63 | win.addEventListener('open', function(){ 64 | 65 | // ...to access activity and action bar 66 | var activity = win.getActivity(); 67 | var actionbar = activity.getActionBar(); 68 | 69 | if (actionbar){ 70 | 71 | // this makes the drawer indicator visible in the action bar 72 | actionbar.displayHomeAsUp = true; 73 | 74 | // open and close with the app icon 75 | actionbar.onHomeIconItemSelected = function() { 76 | drawer.toggleLeftWindow(); 77 | }; 78 | } 79 | }); 80 | 81 | // open the window 82 | win.open(); 83 | ``` 84 | 85 | #### [API Documentation](documentation/index.md) 86 | #### [Demo App](https://github.com/manumaticx/NavigationDrawer-Demo) 87 | 88 | ## Development 89 | 90 | Contributions are very welcome. If you are able to fix bugs or want to add features to the module, please refer to the [official module development guide](http://docs.appcelerator.com/platform/latest/#!/guide/Android_Module_Development_Guide). You can build the module with `appc` as described there. You can also use `grunt build` here. For distribution a new version, please update the version number in `package.json` and run `grunt`. It will update the version number in manifest and readme. Then it builds the new version and installs it globally with `gittio`. 91 | 92 | ## License 93 | 94 | MIT license, see [LICENSE](LICENSE) 95 | 96 | Copyright (c) 2013 - 2014 by Tripvi Inc., 2015 - 2016 by Manuel Lehner 97 | 98 | -------------------------------------------------------------------------------- /android/assets/README: -------------------------------------------------------------------------------- 1 | Place your assets like PNG files in this directory and they will be packaged with your module. 2 | 3 | If you create a file named com.tripvi.drawerlayout.js in this directory, it will be 4 | compiled and used as your module. This allows you to run pure Javascript 5 | modules that are pre-compiled. 6 | 7 | -------------------------------------------------------------------------------- /android/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ant build script for Titanium Android module drawerlayout 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/dist/com.tripvi.drawerlayout-android-1.4.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manumaticx/Ti.DrawerLayout/48bd052446172905d24ae545568215a3fe7ffd4a/android/dist/com.tripvi.drawerlayout-android-1.4.0.zip -------------------------------------------------------------------------------- /android/dist/com.tripvi.drawerlayout-android-1.4.2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manumaticx/Ti.DrawerLayout/48bd052446172905d24ae545568215a3fe7ffd4a/android/dist/com.tripvi.drawerlayout-android-1.4.2.zip -------------------------------------------------------------------------------- /android/dist/com.tripvi.drawerlayout-android-2.0.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manumaticx/Ti.DrawerLayout/48bd052446172905d24ae545568215a3fe7ffd4a/android/dist/com.tripvi.drawerlayout-android-2.0.0.zip -------------------------------------------------------------------------------- /android/dist/com.tripvi.drawerlayout-android-3.0.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manumaticx/Ti.DrawerLayout/48bd052446172905d24ae545568215a3fe7ffd4a/android/dist/com.tripvi.drawerlayout-android-3.0.0.zip -------------------------------------------------------------------------------- /android/dist/com.tripvi.drawerlayout-android-3.0.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manumaticx/Ti.DrawerLayout/48bd052446172905d24ae545568215a3fe7ffd4a/android/dist/com.tripvi.drawerlayout-android-3.0.1.zip -------------------------------------------------------------------------------- /android/dist/drawerlayout.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manumaticx/Ti.DrawerLayout/48bd052446172905d24ae545568215a3fe7ffd4a/android/dist/drawerlayout.jar -------------------------------------------------------------------------------- /android/lib/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manumaticx/Ti.DrawerLayout/48bd052446172905d24ae545568215a3fe7ffd4a/android/lib/.gitkeep -------------------------------------------------------------------------------- /android/manifest: -------------------------------------------------------------------------------- 1 | version: 3.0.1 2 | apiversion: 4 3 | architectures: arm64-v8a armeabi-v7a x86 4 | description: Native Android DrawerLayout for Titanium 5 | author: metacortex, manumaticx 6 | license: MIT license 7 | copyright: Copyright (c) 2013 - 2014 by Tripvi Inc., 2015 - 2016 by Manuel Lehner 8 | 9 | # these should not be edited 10 | name: drawerlayout 11 | moduleid: com.tripvi.drawerlayout 12 | guid: f0a61bb9-3c4d-457f-84c7-3980a13e3dd2 13 | platform: android 14 | minsdk: 7.0.0 15 | -------------------------------------------------------------------------------- /android/platform/README: -------------------------------------------------------------------------------- 1 | You can place platform-specific files here in sub-folders named "android" and/or "iphone", just as you can with normal Titanium Mobile SDK projects. Any folders and files you place here will be merged with the platform-specific files in a Titanium Mobile project that uses this module. 2 | 3 | When a Titanium Mobile project that uses this module is built, the files from this platform/ folder will be treated the same as files (if any) from the Titanium Mobile project's platform/ folder. 4 | -------------------------------------------------------------------------------- /android/platform/android/res/layout/drawer_main.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 14 | 15 | 26 | 27 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /android/platform/android/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Open 4 | Close 5 | -------------------------------------------------------------------------------- /android/src/com/tripvi/drawerlayout/ContentFrame.java: -------------------------------------------------------------------------------- 1 | package com.tripvi.drawerlayout; 2 | 3 | import org.appcelerator.titanium.view.TiCompositeLayout; 4 | 5 | import android.content.Context; 6 | import android.util.AttributeSet; 7 | 8 | public class ContentFrame extends TiCompositeLayout { 9 | private static final String TAG = "TripviContentFrame"; 10 | 11 | public ContentFrame(Context context) { 12 | super(context); 13 | } 14 | 15 | public ContentFrame(Context context, AttributeSet set) { 16 | super(context, set); 17 | setId(Drawer.id_content_frame); 18 | 19 | } 20 | 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /android/src/com/tripvi/drawerlayout/Drawer.java: -------------------------------------------------------------------------------- 1 | package com.tripvi.drawerlayout; 2 | 3 | import android.app.Activity; 4 | import android.support.v7.widget.Toolbar; 5 | import android.view.*; 6 | import org.appcelerator.kroll.KrollDict; 7 | import org.appcelerator.kroll.KrollProxy; 8 | import org.appcelerator.titanium.TiBaseActivity; 9 | import org.appcelerator.titanium.TiDimension; 10 | import org.appcelerator.titanium.TiC; 11 | import org.appcelerator.titanium.proxy.TiViewProxy; 12 | import org.appcelerator.titanium.util.TiConvert; 13 | import org.appcelerator.titanium.util.TiRHelper; 14 | import org.appcelerator.titanium.util.TiRHelper.ResourceNotFoundException; 15 | import org.appcelerator.titanium.view.TiCompositeLayout; 16 | import org.appcelerator.titanium.view.TiUIView; 17 | 18 | import ti.modules.titanium.ui.WindowProxy; 19 | import android.support.v4.widget.DrawerLayout; 20 | import android.support.v4.widget.DrawerLayout.LayoutParams; 21 | import android.support.v4.widget.ViewDragHelper; 22 | import android.support.v7.app.AppCompatActivity; 23 | import android.support.v7.app.ActionBarDrawerToggle; 24 | import android.util.Log; 25 | import android.widget.FrameLayout; 26 | import java.lang.reflect.Field; 27 | 28 | public class Drawer extends TiUIView { 29 | 30 | private ActionBarDrawerToggle mDrawerToggle; 31 | 32 | private FrameLayout menu; /* left drawer */ 33 | private FrameLayout filter; /* right drawer */ 34 | private int menuWidth; 35 | private int filterWidth; 36 | private boolean hasMenu = false; 37 | private boolean hasFilter = false; 38 | private boolean setToolbar = false; 39 | private boolean hasToggle = true; 40 | private boolean hideToolbar = false; 41 | 42 | private TiViewProxy leftView; 43 | private TiViewProxy rightView; 44 | private TiViewProxy centerView; 45 | private Toolbar toolbar; 46 | 47 | // Static Properties 48 | public static final String PROPERTY_LEFT_VIEW = "leftView"; 49 | public static final String PROPERTY_CENTER_VIEW = "centerView"; 50 | public static final String PROPERTY_RIGHT_VIEW = "rightView"; 51 | public static final String PROPERTY_LEFT_VIEW_WIDTH = "leftDrawerWidth"; 52 | public static final String PROPERTY_RIGHT_VIEW_WIDTH = "rightDrawerWidth"; 53 | public static final String PROPERTY_DRAWER_INDICATOR_ENABLED = "drawerIndicatorEnabled"; 54 | public static final String PROPERTY_DRAWER_INDICATOR_IMAGE = "drawerIndicatorImage"; 55 | public static final String PROPERTY_RIGHT_DRAWER_LOCK_MODE = "rightDrawerLockMode"; 56 | public static final String PROPERTY_LEFT_DRAWER_LOCK_MODE = "leftDrawerLockMode"; 57 | public static final String PROPERTY_DRAWER_LOCK_MODE = "drawerLockMode"; 58 | public static final String PROPERTY_HIDE_TOOLBAR = "hideToolbar"; 59 | public static final String PROPERTY_SWIPE_AREA_WIDTH = "dragMargin"; 60 | 61 | private static final String TAG = "TripviDrawer"; 62 | 63 | int string_drawer_open = 0; 64 | int string_drawer_close = 0; 65 | int layout_drawer_main = 0; 66 | public static int id_content_frame = 0; 67 | public static int id_main_container = 0; 68 | public static int id_toolbar = 0; 69 | 70 | public Drawer(final DrawerProxy proxy) { 71 | super(proxy); 72 | 73 | try { 74 | string_drawer_open = TiRHelper.getResource("string.drawer_open"); 75 | string_drawer_close = TiRHelper.getResource("string.drawer_close"); 76 | layout_drawer_main = TiRHelper.getResource("layout.drawer_main"); 77 | id_content_frame = TiRHelper.getResource("id.content_frame"); 78 | id_main_container = TiRHelper.getResource("id.main_container"); 79 | id_toolbar = TiRHelper.getResource("id.toolbar"); 80 | } catch (ResourceNotFoundException e) { 81 | Log.e(TAG, "XML resources could not be found!!!"); 82 | } 83 | 84 | AppCompatActivity activity = (AppCompatActivity) proxy.getActivity(); 85 | 86 | // DrawerLayout 87 | LayoutInflater inflater = LayoutInflater.from(activity); 88 | DrawerLayout layout = (DrawerLayout) inflater.inflate(layout_drawer_main, null, 89 | false); 90 | 91 | layout.setDrawerListener(new DrawerListener()); 92 | 93 | toolbar = (Toolbar)layout.findViewById(id_toolbar); 94 | // If no actionbar exists, 95 | if (activity.getSupportActionBar() == null && activity.getActionBar() == null) { 96 | setToolbar = true; 97 | activity.setSupportActionBar(toolbar); 98 | if (!hideToolbar) { 99 | setToolbarVisible(true); 100 | } 101 | } 102 | 103 | // TiUIView 104 | setNativeView(layout); 105 | 106 | } 107 | 108 | private void setToolbarVisible(boolean isVisible) { 109 | if (isVisible) { 110 | toolbar.setVisibility(View.VISIBLE); 111 | } else { 112 | toolbar.setVisibility(View.GONE); 113 | } 114 | } 115 | 116 | private class DrawerListener implements DrawerLayout.DrawerListener { 117 | 118 | @Override 119 | public void onDrawerClosed(View drawerView) { 120 | if (proxy.hasListeners("drawerclose")) { 121 | KrollDict options = new KrollDict(); 122 | if (drawerView.equals(menu)) { 123 | options.put("drawer", "left"); 124 | } else if (drawerView.equals(filter)) { 125 | options.put("drawer", "right"); 126 | } 127 | proxy.fireEvent("drawerclose", options); 128 | } 129 | } 130 | 131 | @Override 132 | public void onDrawerOpened(View drawerView) { 133 | if (proxy.hasListeners("draweropen")) { 134 | KrollDict options = new KrollDict(); 135 | if (drawerView.equals(menu)) { 136 | options.put("drawer", "left"); 137 | } else if (drawerView.equals(filter)) { 138 | options.put("drawer", "right"); 139 | } 140 | proxy.fireEvent("draweropen", options); 141 | } 142 | } 143 | 144 | @Override 145 | public void onDrawerSlide(View drawerView, float slideOffset) { 146 | if (proxy.hasListeners("drawerslide")) { 147 | KrollDict options = new KrollDict(); 148 | options.put("offset", slideOffset); 149 | if (drawerView.equals(menu)) { 150 | options.put("drawer", "left"); 151 | } else if (drawerView.equals(filter)) { 152 | options.put("drawer", "right"); 153 | } 154 | proxy.fireEvent("drawerslide", options); 155 | } 156 | } 157 | 158 | @Override 159 | public void onDrawerStateChanged(int newState) { 160 | if (proxy.hasListeners("change")) { 161 | KrollDict options = new KrollDict(); 162 | options.put("state", newState); 163 | options.put("idle", (newState == 0 ? 1 : 0)); 164 | options.put("dragging", (newState == 1 ? 1 : 0)); 165 | options.put("settling", (newState == 2 ? 1 : 0)); 166 | proxy.fireEvent("change", options); 167 | } 168 | } 169 | } 170 | 171 | /** 172 | * Open/Close/Toggle drawers 173 | */ 174 | public void toggleLeftDrawer() { 175 | if (((DrawerLayout)getNativeView()).isDrawerOpen(Gravity.START)) { 176 | closeLeftDrawer(); 177 | } else { 178 | openLeftDrawer(); 179 | } 180 | } 181 | 182 | public void openLeftDrawer() { 183 | ((DrawerLayout) getNativeView()).openDrawer(Gravity.START); 184 | } 185 | 186 | public void closeLeftDrawer() { 187 | ((DrawerLayout) getNativeView()).closeDrawer(Gravity.START); 188 | } 189 | 190 | public void toggleRightDrawer() { 191 | if (((DrawerLayout)getNativeView()).isDrawerOpen(Gravity.END)) { 192 | closeRightDrawer(); 193 | } else { 194 | openRightDrawer(); 195 | } 196 | } 197 | 198 | public void openRightDrawer() { 199 | ((DrawerLayout) getNativeView()).openDrawer(Gravity.END); 200 | } 201 | 202 | public void closeRightDrawer() { 203 | ((DrawerLayout) getNativeView()).closeDrawer(Gravity.END); 204 | } 205 | 206 | public boolean isLeftDrawerOpen() { 207 | return ((DrawerLayout) getNativeView()).isDrawerOpen(Gravity.START); 208 | } 209 | 210 | public boolean isRightDrawerOpen() { 211 | return ((DrawerLayout) getNativeView()).isDrawerOpen(Gravity.END); 212 | } 213 | 214 | public boolean isLeftDrawerVisible() { 215 | return ((DrawerLayout) getNativeView()).isDrawerVisible(Gravity.START); 216 | } 217 | 218 | public boolean isRightDrawerVisible() { 219 | return ((DrawerLayout) getNativeView()).isDrawerVisible(Gravity.END); 220 | } 221 | 222 | private void initDrawerToggle() { 223 | 224 | AppCompatActivity activity = (AppCompatActivity) proxy.getActivity(); 225 | 226 | if (activity.getSupportActionBar() == null) { 227 | return; 228 | } 229 | 230 | // enable ActionBar app icon to behave as action to toggle nav 231 | // drawer 232 | activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true); 233 | activity.getSupportActionBar().setHomeButtonEnabled(true); 234 | 235 | // ActionBarDrawerToggle ties together the the proper interactions 236 | // between the sliding drawer and the action bar app icon 237 | mDrawerToggle = new ActionBarDrawerToggle(activity, ((DrawerLayout) getNativeView()), 238 | string_drawer_open, string_drawer_close) { 239 | @Override 240 | public void onDrawerClosed(View drawerView) { 241 | if(!drawerView.equals(menu)){ 242 | return; 243 | } 244 | super.onDrawerClosed(drawerView); 245 | if (proxy.hasListeners("drawerclose")) { 246 | KrollDict options = new KrollDict(); 247 | if (drawerView.equals(menu)) { 248 | options.put("drawer", "left"); 249 | } else if (drawerView.equals(filter)) { 250 | options.put("drawer", "right"); 251 | } 252 | proxy.fireEvent("drawerclose", options); 253 | } 254 | } 255 | 256 | @Override 257 | public void onDrawerOpened(View drawerView) { 258 | if(!drawerView.equals(menu)){ 259 | return; 260 | } 261 | super.onDrawerOpened(drawerView); 262 | if (proxy.hasListeners("draweropen")) { 263 | KrollDict options = new KrollDict(); 264 | if (drawerView.equals(menu)) { 265 | options.put("drawer", "left"); 266 | } else if (drawerView.equals(filter)) { 267 | options.put("drawer", "right"); 268 | } 269 | proxy.fireEvent("draweropen", options); 270 | } 271 | } 272 | 273 | @Override 274 | public void onDrawerSlide(View drawerView, float slideOffset) { 275 | 276 | if(!drawerView.equals(menu)){ 277 | return; 278 | } 279 | 280 | super.onDrawerSlide(drawerView, slideOffset); 281 | if (proxy.hasListeners("drawerslide")) { 282 | KrollDict options = new KrollDict(); 283 | options.put("offset", slideOffset); 284 | if (drawerView.equals(menu)) { 285 | options.put("drawer", "left"); 286 | } else if (drawerView.equals(filter)) { 287 | options.put("drawer", "right"); 288 | } 289 | proxy.fireEvent("drawerslide", options); 290 | } 291 | } 292 | 293 | @Override 294 | public void onDrawerStateChanged(int newState) { 295 | super.onDrawerStateChanged(newState); 296 | 297 | if (proxy.hasListeners("change")) { 298 | KrollDict options = new KrollDict(); 299 | options.put("state", newState); 300 | options.put("idle", (newState == 0 ? 1 : 0)); 301 | options.put("dragging", (newState == 1 ? 1 : 0)); 302 | options.put("settling", (newState == 2 ? 1 : 0)); 303 | proxy.fireEvent("change", options); 304 | } 305 | } 306 | }; 307 | // Set the drawer toggle as the DrawerListener 308 | ((DrawerLayout) getNativeView()).setDrawerListener(mDrawerToggle); 309 | 310 | // onPostCreate 311 | ((DrawerLayout) getNativeView()).post(new Runnable() { 312 | @Override 313 | public void run() { 314 | mDrawerToggle.syncState(); 315 | } 316 | }); 317 | } 318 | 319 | /** 320 | * drawer 321 | */ 322 | private void initLeftDrawer() { 323 | if (hasMenu) { 324 | return; 325 | } 326 | 327 | Log.d(TAG, "initializing left drawer"); 328 | 329 | // menu: left drawer 330 | menu = new FrameLayout(proxy.getActivity()); 331 | LayoutParams menuLayout = new LayoutParams(LayoutParams.WRAP_CONTENT, 332 | LayoutParams.MATCH_PARENT); 333 | menuLayout.gravity = Gravity.START; 334 | menu.setLayoutParams(menuLayout); 335 | 336 | ((DrawerLayout) getNativeView()).addView(menu); 337 | 338 | hasMenu = true; 339 | 340 | if (hasToggle) { 341 | initDrawerToggle(); 342 | } 343 | } 344 | 345 | private void initRightDrawer() { 346 | if (hasFilter) { 347 | return; 348 | } 349 | 350 | Log.d(TAG, "initializing right drawer"); 351 | 352 | // filter: right drawer 353 | filter = new FrameLayout(proxy.getActivity()); 354 | LayoutParams filterLayout = new LayoutParams(LayoutParams.WRAP_CONTENT, 355 | LayoutParams.MATCH_PARENT); 356 | filterLayout.gravity = Gravity.END; 357 | filter.setLayoutParams(filterLayout); 358 | 359 | ((DrawerLayout) getNativeView()).addView(filter); 360 | 361 | hasFilter = true; 362 | } 363 | 364 | /** 365 | * centerView 366 | */ 367 | public void replaceCenterView(TiViewProxy viewProxy) { 368 | if (viewProxy == this.centerView) { 369 | Log.d(TAG, "centerView was not changed"); 370 | return; 371 | } 372 | if (viewProxy == null) { 373 | return; 374 | } 375 | 376 | viewProxy.setActivity(proxy.getActivity()); 377 | TiUIView contentView = getOrCreateView(viewProxy); 378 | 379 | View view = contentView.getOuterView(); 380 | TiCompositeLayout fL = (TiCompositeLayout)getNativeView().findViewById(id_content_frame); 381 | ViewParent viewParent = view.getParent(); 382 | if (viewParent == null) { 383 | fL.addView(view, contentView.getLayoutParams()); 384 | } 385 | if (viewParent instanceof ViewGroup && viewParent != fL) { 386 | ((ViewGroup)viewParent).removeView(view); 387 | fL.addView(view, contentView.getLayoutParams()); 388 | } 389 | if (this.centerView != null) { 390 | fL.removeView(getOrCreateView(this.centerView).getNativeView()); 391 | this.centerView.releaseViews(); 392 | } 393 | this.centerView = viewProxy; 394 | } 395 | 396 | public void setArrowState (Float state){ 397 | // leaving this here for now, maybe replace it later 398 | } 399 | 400 | private void setSwipeArea (Integer width){ 401 | try{ 402 | Field mDragger = getNativeView().getClass().getDeclaredField("mLeftDragger"); 403 | mDragger.setAccessible(true); 404 | ViewDragHelper draggerObj = (ViewDragHelper) mDragger.get(getNativeView()); 405 | Field mEdgeSize = draggerObj.getClass().getDeclaredField("mEdgeSize"); 406 | mEdgeSize.setAccessible(true); 407 | mEdgeSize.setInt(draggerObj, width); 408 | }catch(NoSuchFieldException e){ 409 | Log.e(TAG, e.toString()); 410 | }catch(IllegalAccessException e){ 411 | Log.e(TAG, e.toString()); 412 | } 413 | } 414 | 415 | @Override 416 | public void processProperties(KrollDict d) { 417 | if (d.containsKey(PROPERTY_DRAWER_INDICATOR_ENABLED)) { 418 | hasToggle = TiConvert.toBoolean(d, 419 | PROPERTY_DRAWER_INDICATOR_ENABLED); 420 | } 421 | 422 | if (d.containsKey(PROPERTY_LEFT_VIEW)) { 423 | Object leftView = d.get(PROPERTY_LEFT_VIEW); 424 | if (leftView != null && leftView instanceof TiViewProxy) { 425 | if (leftView instanceof WindowProxy) 426 | throw new IllegalStateException( 427 | "[ERROR] Cannot add window as a child view of other window"); 428 | // 429 | this.leftView = (TiViewProxy) leftView; 430 | this.initLeftDrawer(); 431 | this.menu.addView(getNativeView(this.leftView)); 432 | } else { 433 | Log.e(TAG, "[ERROR] Invalid type for leftView"); 434 | } 435 | } 436 | if (d.containsKey(PROPERTY_RIGHT_VIEW)) { 437 | Object rightView = d.get(PROPERTY_RIGHT_VIEW); 438 | if (rightView != null && rightView instanceof TiViewProxy) { 439 | if (rightView instanceof WindowProxy) 440 | throw new IllegalStateException( 441 | "[ERROR] Cannot add window as a child view of other window"); 442 | this.rightView = (TiViewProxy) rightView; 443 | this.initRightDrawer(); 444 | this.filter.addView(getNativeView(this.rightView)); 445 | } else { 446 | Log.e(TAG, "[ERROR] Invalid type for rightView"); 447 | } 448 | } 449 | if (d.containsKey(PROPERTY_CENTER_VIEW)) { 450 | Object centerView = d.get(PROPERTY_CENTER_VIEW); 451 | if (centerView != null && centerView instanceof TiViewProxy) { 452 | if (centerView instanceof WindowProxy) 453 | throw new IllegalStateException( 454 | "[ERROR] Cannot use window as a child view of other window"); 455 | replaceCenterView((TiViewProxy) centerView); 456 | } else { 457 | Log.e(TAG, "[ERROR] Invalid type for centerView"); 458 | } 459 | } 460 | if (d.containsKey(PROPERTY_LEFT_VIEW_WIDTH)) { 461 | 462 | if (menu != null){ 463 | if (d.get(PROPERTY_LEFT_VIEW_WIDTH).equals(TiC.LAYOUT_SIZE)) { 464 | menu.getLayoutParams().width = LayoutParams.WRAP_CONTENT; 465 | } else if (d.get(PROPERTY_LEFT_VIEW_WIDTH).equals(TiC.LAYOUT_FILL)) { 466 | menu.getLayoutParams().width = LayoutParams.MATCH_PARENT; 467 | } else if (!d.get(PROPERTY_LEFT_VIEW_WIDTH).equals(TiC.SIZE_AUTO)) { 468 | menuWidth = getDevicePixels(d.get(PROPERTY_LEFT_VIEW_WIDTH)); 469 | menu.getLayoutParams().width = menuWidth; 470 | } 471 | } 472 | } else { 473 | if (menu != null){ 474 | menu.getLayoutParams().width = LayoutParams.MATCH_PARENT; 475 | } 476 | } 477 | if (d.containsKey(PROPERTY_RIGHT_VIEW_WIDTH)) { 478 | 479 | if (filter != null){ 480 | if (d.get(PROPERTY_RIGHT_VIEW_WIDTH).equals(TiC.LAYOUT_SIZE)) { 481 | filter.getLayoutParams().width = LayoutParams.WRAP_CONTENT; 482 | } else if (d.get(PROPERTY_RIGHT_VIEW_WIDTH).equals(TiC.LAYOUT_FILL)) { 483 | filter.getLayoutParams().width = LayoutParams.MATCH_PARENT; 484 | } else if (!d.get(PROPERTY_RIGHT_VIEW_WIDTH).equals(TiC.SIZE_AUTO)) { 485 | filterWidth = getDevicePixels(d.get(PROPERTY_RIGHT_VIEW_WIDTH)); 486 | filter.getLayoutParams().width = filterWidth; 487 | } 488 | } 489 | } else { 490 | if (filter != null){ 491 | filter.getLayoutParams().width = LayoutParams.MATCH_PARENT; 492 | } 493 | } 494 | if (d.containsKey(PROPERTY_DRAWER_LOCK_MODE)) { 495 | ((DrawerLayout) getNativeView()).setDrawerLockMode(TiConvert.toInt(d 496 | .get(PROPERTY_DRAWER_LOCK_MODE))); 497 | } 498 | if (d.containsKey(PROPERTY_LEFT_DRAWER_LOCK_MODE)) { 499 | setLeftDrawerLockMode(TiConvert.toInt(d 500 | .get(PROPERTY_LEFT_DRAWER_LOCK_MODE))); 501 | } 502 | if (d.containsKey(PROPERTY_RIGHT_DRAWER_LOCK_MODE)) { 503 | setRightDrawerLockMode(TiConvert.toInt(d 504 | .get(PROPERTY_RIGHT_DRAWER_LOCK_MODE))); 505 | } 506 | if (d.containsKey(PROPERTY_HIDE_TOOLBAR)) { 507 | hideToolbar = (TiConvert.toBoolean(d.get(PROPERTY_HIDE_TOOLBAR))); 508 | if (hideToolbar) { 509 | setToolbarVisible(false); 510 | } else { 511 | setToolbarVisible(true); 512 | } 513 | } 514 | if (d.containsKey(PROPERTY_SWIPE_AREA_WIDTH)){ 515 | setSwipeArea(getDevicePixels(d.get(PROPERTY_SWIPE_AREA_WIDTH))); 516 | } 517 | 518 | super.processProperties(d); 519 | } 520 | 521 | @Override 522 | public void propertyChanged(String key, Object oldValue, Object newValue, 523 | KrollProxy proxy) { 524 | 525 | Log.d(TAG, "propertyChanged Property: " + key + " old: " + oldValue 526 | + " new: " + newValue); 527 | 528 | if (key.equals(PROPERTY_LEFT_VIEW)) { 529 | if (newValue == this.leftView) 530 | return; 531 | TiViewProxy newProxy = null; 532 | int index = 0; 533 | if (this.leftView != null) { 534 | index = this.menu.indexOfChild(getOrCreateView(this.leftView) 535 | .getNativeView()); 536 | } 537 | if (newValue != null && newValue instanceof TiViewProxy) { 538 | if (newValue instanceof WindowProxy) 539 | throw new IllegalStateException( 540 | "[ERROR] Cannot add window as a child view of other window"); 541 | newProxy = (TiViewProxy) newValue; 542 | initLeftDrawer(); 543 | this.menu.addView(getOrCreateView(newProxy).getOuterView(), 544 | index); 545 | } else { 546 | Log.e(TAG, "[ERROR] Invalid type for leftView"); 547 | } 548 | if (this.leftView != null) { 549 | this.menu.removeView(getOrCreateView(this.leftView) 550 | .getNativeView()); 551 | } 552 | this.leftView = newProxy; 553 | } else if (key.equals(PROPERTY_RIGHT_VIEW)) { 554 | if (newValue == this.rightView) 555 | return; 556 | TiViewProxy newProxy = null; 557 | int index = 0; 558 | if (this.rightView != null) { 559 | index = this.filter.indexOfChild( 560 | getOrCreateView(this.rightView).getNativeView()); 561 | } 562 | if (newValue != null && newValue instanceof TiViewProxy) { 563 | if (newValue instanceof WindowProxy) 564 | throw new IllegalStateException( 565 | "[ERROR] Cannot add window as a child view of other window"); 566 | newProxy = (TiViewProxy) newValue; 567 | initRightDrawer(); 568 | this.filter.addView(getOrCreateView(newProxy).getOuterView(), 569 | index); 570 | } else { 571 | Log.e(TAG, "[ERROR] Invalid type for rightView"); 572 | } 573 | if (this.rightView != null) { 574 | this.filter.removeView(getOrCreateView(this.rightView) 575 | .getNativeView()); 576 | } 577 | this.rightView = newProxy; 578 | } else if (key.equals(PROPERTY_CENTER_VIEW)) { 579 | TiViewProxy newProxy = (TiViewProxy) newValue; 580 | replaceCenterView(newProxy); 581 | } else if (key.equals(PROPERTY_LEFT_VIEW_WIDTH)) { 582 | 583 | if (menu == null){ 584 | return; 585 | } 586 | 587 | initLeftDrawer(); 588 | 589 | if (newValue.equals(TiC.LAYOUT_SIZE)) { 590 | menuWidth = LayoutParams.WRAP_CONTENT; 591 | } else if (newValue.equals(TiC.LAYOUT_FILL)) { 592 | menuWidth = LayoutParams.MATCH_PARENT; 593 | } else if (!newValue.equals(TiC.SIZE_AUTO)) { 594 | menuWidth = getDevicePixels(newValue); 595 | } 596 | 597 | LayoutParams menuLayout = new LayoutParams(menuWidth, 598 | LayoutParams.MATCH_PARENT); 599 | menuLayout.gravity = Gravity.START; 600 | this.menu.setLayoutParams(menuLayout); 601 | 602 | } else if (key.equals(PROPERTY_RIGHT_VIEW_WIDTH)) { 603 | 604 | if (filter == null){ 605 | return; 606 | } 607 | 608 | initRightDrawer(); 609 | 610 | if (newValue.equals(TiC.LAYOUT_SIZE)) { 611 | filterWidth = LayoutParams.WRAP_CONTENT; 612 | } else if (newValue.equals(TiC.LAYOUT_FILL)) { 613 | filterWidth = LayoutParams.MATCH_PARENT; 614 | } else if (!newValue.equals(TiC.SIZE_AUTO)) { 615 | filterWidth = getDevicePixels(newValue); 616 | } 617 | 618 | LayoutParams filterLayout = new LayoutParams(filterWidth, 619 | LayoutParams.MATCH_PARENT); 620 | filterLayout.gravity = Gravity.END; 621 | this.filter.setLayoutParams(filterLayout); 622 | 623 | } else if (key.equals(PROPERTY_DRAWER_LOCK_MODE)) { 624 | ((DrawerLayout) getNativeView()).setDrawerLockMode(TiConvert.toInt(newValue)); 625 | } else if (key.equals(PROPERTY_LEFT_DRAWER_LOCK_MODE)) { 626 | this.setLeftDrawerLockMode(TiConvert.toInt(newValue)); 627 | } else if (key.equals(PROPERTY_RIGHT_DRAWER_LOCK_MODE)) { 628 | this.setRightDrawerLockMode(TiConvert.toInt(newValue)); 629 | } else if (key.equals(PROPERTY_DRAWER_INDICATOR_ENABLED)) { 630 | boolean b = (Boolean) newValue; 631 | if (mDrawerToggle != null){ 632 | mDrawerToggle.setDrawerIndicatorEnabled(b); 633 | } 634 | } else if (key.equals(PROPERTY_HIDE_TOOLBAR)) { 635 | hideToolbar = (TiConvert.toBoolean(newValue)); 636 | if (hideToolbar) { 637 | setToolbarVisible(false); 638 | } else { 639 | setToolbarVisible(true); 640 | } 641 | } else if (key.equals(PROPERTY_SWIPE_AREA_WIDTH)){ 642 | setSwipeArea(getDevicePixels(newValue)); 643 | } else { 644 | super.propertyChanged(key, oldValue, newValue, proxy); 645 | } 646 | } 647 | 648 | public void setLeftDrawerLockMode(int mode) { 649 | setDrawerLockMode(mode, Gravity.START); 650 | } 651 | 652 | public void setRightDrawerLockMode(int mode) { 653 | setDrawerLockMode(mode, Gravity.END); 654 | } 655 | 656 | private void setDrawerLockMode(int mode, int gravity) { 657 | ((DrawerLayout) getNativeView()).setDrawerLockMode(mode, gravity); 658 | } 659 | 660 | @Override 661 | public void release() { 662 | Log.d(TAG, "release"); 663 | DrawerLayout layout = (DrawerLayout) getNativeView(); 664 | if (layout != null) { 665 | layout.removeAllViews(); 666 | layout.setDrawerListener(null); 667 | } 668 | if (menu != null) { 669 | menu.removeAllViews(); 670 | menu = null; 671 | } 672 | if (filter != null) { 673 | filter.removeAllViews(); 674 | filter = null; 675 | } 676 | if (leftView != null) { 677 | leftView.releaseViews(); 678 | leftView = null; 679 | } 680 | if (rightView != null) { 681 | rightView.releaseViews(); 682 | rightView = null; 683 | } 684 | if (centerView != null) { 685 | centerView.releaseViews(); 686 | centerView = null; 687 | } 688 | if (setToolbar) { 689 | AppCompatActivity activity = (AppCompatActivity) proxy.getActivity(); 690 | toolbar.removeAllViews(); 691 | toolbar = null; 692 | } 693 | super.release(); 694 | proxy = null; 695 | } 696 | 697 | /** 698 | * Helpers 699 | */ 700 | public int getDevicePixels(Object value) { 701 | TiDimension nativeSize = TiConvert.toTiDimension(TiConvert.toString(value), TiDimension.TYPE_WIDTH); 702 | return nativeSize.getAsPixels(getNativeView()); 703 | } 704 | 705 | private View getNativeView(TiViewProxy viewProxy) { 706 | View nativeView = getOrCreateView(viewProxy).getOuterView(); 707 | ViewGroup parentViewGroup = (ViewGroup) nativeView.getParent(); 708 | if (parentViewGroup != null) { 709 | parentViewGroup.removeAllViews(); 710 | } 711 | return nativeView; 712 | } 713 | 714 | private TiUIView getOrCreateView(TiViewProxy viewProxy) { 715 | if (viewProxy == null) { 716 | return null; 717 | } 718 | TiUIView view = viewProxy.getOrCreateView(); 719 | if (view != null) { 720 | return view; 721 | } 722 | Log.w(TAG, "getOrCreateView failed. Returned value is null"); 723 | TiBaseActivity originalActivity = (TiBaseActivity) viewProxy.getActivity(); 724 | if (originalActivity.isDestroyed()) { 725 | Log.w(TAG, "Original viewProxy activity is destroyed."); 726 | } 727 | Activity thisActivity = this.proxy.getActivity(); 728 | if (thisActivity != originalActivity) { 729 | viewProxy.attachActivityLifecycle(thisActivity); 730 | } 731 | return viewProxy.getOrCreateView(); 732 | } 733 | } 734 | -------------------------------------------------------------------------------- /android/src/com/tripvi/drawerlayout/DrawerProxy.java: -------------------------------------------------------------------------------- 1 | package com.tripvi.drawerlayout; 2 | 3 | import org.appcelerator.kroll.annotations.Kroll; 4 | import org.appcelerator.titanium.TiApplication; 5 | import org.appcelerator.titanium.proxy.TiViewProxy; 6 | import org.appcelerator.titanium.util.TiConvert; 7 | import org.appcelerator.titanium.view.TiUIView; 8 | 9 | import android.app.Activity; 10 | import android.os.Message; 11 | import android.util.Log; 12 | 13 | @Kroll.proxy(creatableInModule = DrawerlayoutModule.class) 14 | public class DrawerProxy extends TiViewProxy { 15 | 16 | private static final int MSG_FIRST_ID = TiViewProxy.MSG_LAST_ID + 1; 17 | 18 | private static final int MSG_TOGGLE_LEFT_VIEW = MSG_FIRST_ID + 100; 19 | private static final int MSG_TOGGLE_RIGHT_VIEW = MSG_FIRST_ID + 101; 20 | private static final int MSG_OPEN_LEFT_VIEW = MSG_FIRST_ID + 102; 21 | private static final int MSG_OPEN_RIGHT_VIEW = MSG_FIRST_ID + 103; 22 | private static final int MSG_CLOSE_LEFT_VIEW = MSG_FIRST_ID + 104; 23 | private static final int MSG_CLOSE_RIGHT_VIEW = MSG_FIRST_ID + 105; 24 | private static final int MSG_ARROW_STATE = MSG_FIRST_ID + 106; 25 | 26 | protected static final int MSG_LAST_ID = MSG_FIRST_ID + 999; 27 | 28 | private static final String TAG = "TripviDrawerProxy"; 29 | 30 | public DrawerProxy() { 31 | super(); 32 | } 33 | 34 | @Override 35 | public TiUIView createView(Activity activity) { 36 | Drawer drawer = new Drawer(this); 37 | drawer.getLayoutParams().autoFillsHeight = true; 38 | drawer.getLayoutParams().autoFillsWidth = true; 39 | return drawer; 40 | } 41 | 42 | @Override 43 | public boolean handleMessage(Message msg) { 44 | switch (msg.what) { 45 | case MSG_TOGGLE_LEFT_VIEW: { 46 | handleToggleLeftView(); 47 | return true; 48 | } 49 | case MSG_OPEN_LEFT_VIEW: { 50 | handleOpenLeftView(); 51 | return true; 52 | } 53 | case MSG_CLOSE_LEFT_VIEW: { 54 | handleCloseLeftView(); 55 | return true; 56 | } 57 | case MSG_TOGGLE_RIGHT_VIEW: { 58 | handleToggleRightView(); 59 | return true; 60 | } 61 | case MSG_OPEN_RIGHT_VIEW: { 62 | handleOpenRightView(); 63 | return true; 64 | } 65 | case MSG_CLOSE_RIGHT_VIEW: { 66 | handleCloseRightView(); 67 | return true; 68 | } 69 | case MSG_ARROW_STATE: { 70 | handleArrowState((Float) msg.obj); 71 | return true; 72 | } 73 | default: { 74 | return super.handleMessage(msg); 75 | } 76 | } 77 | } 78 | 79 | @Override 80 | public void releaseViews() 81 | { 82 | Log.d(TAG, "DrawerProxy releaseViews"); 83 | super.releaseViews(); 84 | } 85 | 86 | @Override 87 | public void release() { 88 | Log.d(TAG, "DrawerProxy release"); 89 | super.release(); 90 | } 91 | 92 | private void handleToggleLeftView() { 93 | Drawer v = (Drawer) peekView(); 94 | if (v != null) { 95 | v.toggleLeftDrawer(); 96 | } 97 | } 98 | 99 | private void handleOpenLeftView() { 100 | Drawer v = (Drawer) peekView(); 101 | if (v != null) { 102 | v.openLeftDrawer(); 103 | } 104 | } 105 | 106 | private void handleCloseLeftView() { 107 | Drawer v = (Drawer) peekView(); 108 | if (v != null) { 109 | v.closeLeftDrawer(); 110 | } 111 | } 112 | 113 | private void handleToggleRightView() { 114 | Drawer v = (Drawer) peekView(); 115 | if (v != null) { 116 | v.toggleRightDrawer(); 117 | } 118 | } 119 | 120 | private void handleOpenRightView() { 121 | Drawer v = (Drawer) peekView(); 122 | if (v != null) { 123 | v.openRightDrawer(); 124 | } 125 | } 126 | 127 | private void handleCloseRightView() { 128 | Drawer v = (Drawer) peekView(); 129 | if (v != null) { 130 | v.closeRightDrawer(); 131 | } 132 | } 133 | 134 | private void handleArrowState(Float state){ 135 | Drawer v = (Drawer) peekView(); 136 | if (v != null) { 137 | v.setArrowState(state); 138 | } 139 | } 140 | 141 | @Kroll.method 142 | public void toggleLeftWindow(@Kroll.argument(optional = true) Object obj) { 143 | if (TiApplication.isUIThread()) { 144 | handleToggleLeftView(); 145 | return; 146 | } 147 | Message message = getMainHandler().obtainMessage(MSG_TOGGLE_LEFT_VIEW); 148 | message.sendToTarget(); 149 | } 150 | 151 | @Kroll.method 152 | public void openLeftWindow() { 153 | if (TiApplication.isUIThread()) { 154 | handleOpenLeftView(); 155 | return; 156 | } 157 | Message message = getMainHandler().obtainMessage(MSG_OPEN_LEFT_VIEW); 158 | message.sendToTarget(); 159 | } 160 | 161 | @Kroll.method 162 | public void closeLeftWindow() { 163 | if (TiApplication.isUIThread()) { 164 | handleCloseLeftView(); 165 | return; 166 | } 167 | Message message = getMainHandler().obtainMessage(MSG_CLOSE_LEFT_VIEW); 168 | message.sendToTarget(); 169 | } 170 | 171 | @Kroll.method 172 | public void toggleRightWindow(@Kroll.argument(optional = true) Object obj) { 173 | if (TiApplication.isUIThread()) { 174 | handleToggleRightView(); 175 | return; 176 | } 177 | Message message = getMainHandler().obtainMessage(MSG_TOGGLE_RIGHT_VIEW); 178 | message.sendToTarget(); 179 | } 180 | 181 | @Kroll.method 182 | public void openRightWindow() { 183 | if (TiApplication.isUIThread()) { 184 | handleOpenRightView(); 185 | return; 186 | } 187 | Message message = getMainHandler().obtainMessage(MSG_OPEN_RIGHT_VIEW); 188 | message.sendToTarget(); 189 | } 190 | 191 | @Kroll.method 192 | public void closeRightWindow() { 193 | if (TiApplication.isUIThread()) { 194 | handleCloseRightView(); 195 | return; 196 | } 197 | Message message = getMainHandler().obtainMessage(MSG_CLOSE_RIGHT_VIEW); 198 | message.sendToTarget(); 199 | } 200 | 201 | @Kroll.method 202 | @Kroll.getProperty 203 | public boolean getIsLeftDrawerOpen() { 204 | Drawer v = (Drawer) peekView(); 205 | if (v != null) { 206 | return v.isLeftDrawerOpen(); 207 | } else { 208 | return false; 209 | } 210 | } 211 | 212 | @Kroll.method 213 | @Kroll.getProperty 214 | public boolean getIsRightDrawerOpen() { 215 | Drawer v = (Drawer) peekView(); 216 | if (v != null) { 217 | return v.isRightDrawerOpen(); 218 | } else { 219 | return false; 220 | } 221 | } 222 | 223 | @Kroll.method 224 | @Kroll.getProperty 225 | public boolean getIsLeftDrawerVisible() { 226 | Drawer v = (Drawer) peekView(); 227 | if (v != null) { 228 | return v.isLeftDrawerVisible(); 229 | } else { 230 | return false; 231 | } 232 | } 233 | 234 | @Kroll.method 235 | @Kroll.getProperty 236 | public boolean getIsRightDrawerVisible() { 237 | Drawer v = (Drawer) peekView(); 238 | if (v != null) { 239 | return v.isRightDrawerVisible(); 240 | } else { 241 | return false; 242 | } 243 | } 244 | 245 | @Kroll.method 246 | @Kroll.setProperty 247 | public void setLeftDrawerWidth(Object arg) { 248 | setPropertyAndFire(Drawer.PROPERTY_LEFT_VIEW_WIDTH, arg); 249 | } 250 | 251 | @Kroll.method 252 | @Kroll.setProperty 253 | public void setLeftView(Object arg) { 254 | setPropertyAndFire(Drawer.PROPERTY_LEFT_VIEW, arg); 255 | } 256 | 257 | @Kroll.method 258 | @Kroll.setProperty 259 | public void setRightDrawerWidth(Object arg) { 260 | setPropertyAndFire(Drawer.PROPERTY_RIGHT_VIEW_WIDTH, arg); 261 | } 262 | 263 | @Kroll.method 264 | @Kroll.setProperty 265 | public void setRightView(Object arg) { 266 | setPropertyAndFire(Drawer.PROPERTY_RIGHT_VIEW, arg); 267 | } 268 | 269 | @Kroll.method 270 | @Kroll.setProperty 271 | public void setCenterView(Object arg) { 272 | setPropertyAndFire(Drawer.PROPERTY_CENTER_VIEW, arg); 273 | } 274 | 275 | @Kroll.method 276 | public void replaceCenterView(Object arg, boolean backstack) { 277 | Log.w(TAG, "replaceCenterView is deprecated. Please use setCenterView instead."); 278 | setPropertyAndFire(Drawer.PROPERTY_CENTER_VIEW, arg); 279 | } 280 | 281 | @Kroll.method 282 | @Kroll.setProperty 283 | public void setDrawerIndicatorEnabled(Object arg) { 284 | setPropertyAndFire(Drawer.PROPERTY_DRAWER_INDICATOR_ENABLED, arg); 285 | } 286 | 287 | @Kroll.method 288 | @Kroll.setProperty 289 | public void setDrawerLockMode(Object arg) { 290 | setPropertyAndFire(Drawer.PROPERTY_DRAWER_LOCK_MODE, arg); 291 | } 292 | 293 | @Kroll.method 294 | @Kroll.setProperty 295 | public void setLeftDrawerLockMode(Object arg) { 296 | setPropertyAndFire(Drawer.PROPERTY_LEFT_DRAWER_LOCK_MODE, arg); 297 | } 298 | 299 | @Kroll.method 300 | @Kroll.setProperty 301 | public void setRightDrawerLockMode(Object arg) { 302 | setPropertyAndFire(Drawer.PROPERTY_RIGHT_DRAWER_LOCK_MODE, arg); 303 | } 304 | 305 | @Kroll.method 306 | @Kroll.setProperty 307 | public void setDrawerIndicatorImage(Object arg) { 308 | setPropertyAndFire(Drawer.PROPERTY_DRAWER_INDICATOR_IMAGE, arg); 309 | } 310 | 311 | @Kroll.method 312 | public void interceptTouchEvent (TiViewProxy view, Boolean disallowIntercept){ 313 | view.getOrCreateView().getOuterView().getParent().requestDisallowInterceptTouchEvent(disallowIntercept); 314 | } 315 | 316 | @Kroll.method 317 | public void setArrowState (Integer state){ 318 | Message message = getMainHandler().obtainMessage(MSG_ARROW_STATE, TiConvert.toFloat(state, 0)); 319 | message.sendToTarget(); 320 | } 321 | 322 | @Kroll.method 323 | @Kroll.setProperty 324 | public void setToolbarHidden(Object arg) { 325 | setPropertyAndFire(Drawer.PROPERTY_HIDE_TOOLBAR, arg); 326 | } 327 | 328 | } 329 | -------------------------------------------------------------------------------- /android/src/com/tripvi/drawerlayout/DrawerlayoutModule.java: -------------------------------------------------------------------------------- 1 | package com.tripvi.drawerlayout; 2 | 3 | import org.appcelerator.kroll.KrollModule; 4 | import org.appcelerator.kroll.annotations.Kroll; 5 | 6 | import org.appcelerator.titanium.TiApplication; 7 | 8 | import android.support.v4.widget.DrawerLayout; 9 | 10 | @Kroll.module(name = "Drawerlayout", id = "com.tripvi.drawerlayout") 11 | public class DrawerlayoutModule extends KrollModule { 12 | // constants 13 | @Kroll.constant public static final int LOCK_MODE_LOCKED_CLOSED = DrawerLayout.LOCK_MODE_LOCKED_CLOSED; 14 | @Kroll.constant public static final int LOCK_MODE_LOCKED_OPEN = DrawerLayout.LOCK_MODE_LOCKED_OPEN; 15 | @Kroll.constant public static final int LOCK_MODE_UNLOCKED = DrawerLayout.LOCK_MODE_UNLOCKED; 16 | 17 | public DrawerlayoutModule() { 18 | super(); 19 | } 20 | 21 | @Kroll.onAppCreate 22 | public static void onAppCreate(TiApplication app) { 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /android/timodule.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /documentation/index.md: -------------------------------------------------------------------------------- 1 | # Ti.DrawerLayout Documentation 2 | 3 | You can create a Drawer by calling `createDrawer` on the module. It must be added as a top-level view to a Ti.UI.Window. You may want to pass a `contentView` property at creation-time. In addition, you can also pass either a `leftView` or `rightView` property to add an actual drawer view to your layout. All of them (`contentView`, `leftView` and `rightView`) must be instances of Ti.UI.View. 4 | 5 | Here's an example: 6 | 7 | ```javascript 8 | var TiDrawerLayout = require('com.tripvi.drawerlayout'); 9 | var contentView = Ti.UI.createView(); 10 | var leftView = Ti.UI.createTableView({ backgroundColor: '#ccc' }); 11 | 12 | var drawer = TiDrawerLayout.createDrawer({ 13 | centerView: contentView, 14 | leftView: leftView 15 | }); 16 | ``` 17 | 18 | And this is how you'd do it in Alloy: 19 | 20 | ```xml 21 | 22 | 23 | 24 | 25 | 26 | ``` 27 | 28 | ```javascript 29 | var menu = Alloy.createController('menu'); 30 | var main = Alloy.createController('main'); 31 | 32 | $.drawer.setLeftView( menu.getView() ); 33 | $.drawer.setCenterView( main.getView() ); 34 | 35 | ``` 36 | 37 | ## Properties 38 | 39 | * `leftView` _(Ti.UI.View)_ - sets the left drawer 40 | * `rightView` _(Ti.UI.View)_ - sets the right drawer 41 | * `centerView` _(Ti.UI.View)_ - sets the center View 42 | * `isLeftDrawerOpen` _(Boolean)_ - wether the left drawer is currently in an open state or not 43 | * `isLeftDrawerVisible` _(Boolean)_ - wether the left drawer is currently visible on-screen or not 44 | * `isRightDrawerOpen` _(Boolean)_ - wether the right drawer is currently in an open state or not 45 | * `isRightDrawerVisible` _(Boolean)_ - wether the right drawer is currently visible on-screen or not 46 | * `leftDrawerWidth` _(Number/String)_ - sets the width of the left drawer 47 | * `rightDrawerWidth` _(Number/String)_ - sets the width of the right drawer 48 | * `drawerIndicatorEnabled` _(Boolean)_ - wether it should use the ActionBarDrawerToggle or not 49 | * ~~`drawerIndicatorImage`~~ _(String)_ - **(DEPRECATED)** path to a custom drawer indicator image 50 | * `drawerLockMode` _(Number)_ - sets the lock mode constant. TiDrawerLayout.LOCK_MODE_UNLOCKED (default), TiDrawerLayout.LOCK_MODE_LOCKED_CLOSED, TiDrawerLayout.LOCK_MODE_LOCKED_OPEN 51 | * `dragMargin` _(Number)_ - defines the width of the area the user can swipe the drawer in 52 | * `hideToolbar` _(Boolean)_ - hides the toolbar 53 | 54 | ## Methods 55 | 56 | * `setLeftView()` - sets the value for the `leftView` property 57 | * `setRightView()` - sets the value for the `rightView` property 58 | * `setCenterView()` - sets the value for the `centerView` property 59 | * ~~`replaceCenterView(view, backstack)`~~ - **(DEPRECATED)** same as `setCenterView` but with second parameter 60 | * `view` _(Ti.UI.View)_ - the new centerView 61 | * `backstack` _(Boolean)_ - set this to `true` if you want to add this to the backstack 62 | * `toggleLeftWindow()` - opens or closes the left drawer 63 | * `openLeftWindow()` - opens the left drawer 64 | * `closeLeftWindow()` - closes the left drawer 65 | * `toggleRightWindow()` - opens or closes the right drawer 66 | * `openRightWindow()` - opens the right drawer 67 | * `closeRightWindow()` - closes the right drawer 68 | * `getIsLeftDrawerOpen()` - returns the value of the `isLeftDrawerOpen` property 69 | * `getIsLeftDrawerVisible()` - returns the value of the `isLeftDrawerVisible` property 70 | * `getIsRightDrawerOpen()` - returns the value of the `isRightDrawerOpen` property 71 | * `getIsRightDrawerVisible()` - returns the value of the `isRightDrawerVisible` property 72 | * `setLeftDrawerWidth()` - sets the value for the `leftDrawerWidth` property 73 | * `setRightDrawerWidth()` - sets the value for the `rightDrawerWidth` property 74 | * `setDrawerIndicatorEnabled()` - sets the value for the `drawerIndicatorEnabled` property 75 | * ~~`setDrawerIndicatorImage()`~~ - **(DEPRECATED)** sets the value for the `drawerIndicatorImage` property 76 | * `setDrawerLockMode()` - sets the value for the `drawerLockMode` property 77 | * `setLeftDrawerLockMode()` - sets the value for the `drawerLockMode` property for the left drawer 78 | * `setRightDrawerLockMode()` - sets the value for the `drawerLockMode` property for the right drawer 79 | * ~~`setArrowState(value)`~~ - **(DEPRECATED)** sets the state of the drawerArrowIcon 80 | * `value` _(Number)_ - state (1 is arrow, 0 is hamburger, but you can set everything between) 81 | * `setToolbarHidden` - sets the value for `hideToolbar` property 82 | 83 | ## Events 84 | 85 | * `change` - fires when the drawer motion state changes 86 | * `state` _(Number)_ - the new drawer motion state 87 | * `idle` _(Boolean)_ - indicates that any drawers are in an idle, settled state. No animation is in progress 88 | * `dragging` _(Boolean)_ - indicates that a drawer is currently being dragged by the user 89 | * `settling` _(Boolean)_ - indicates that a drawer is in the process of settling to a final position 90 | 91 | * `drawerslide` - fires when a drawer's position changes 92 | * `offset` _(Number)_ - the new offset of this drawer within its range, from 0-1 93 | * `drawer` _(String)_ - left or right 94 | 95 | * `draweropen` - fires when the drawer motion state changes 96 | * `drawer` _(String)_ - left or right 97 | 98 | * `drawerclose` - fires when the drawer motion state changes 99 | * `drawer` _(String)_ - left or right 100 | 101 | ## Tricks & Pitfalls 102 | 103 | * Themes: Actionbar vs. Toolbar 104 | * There are two ways to setup the drawer module according to the App bar: 105 | 1. Traditional: Drawer *below* App bar (using the Actionbar) 106 | * use default `Theme.AppCompat` or `Theme.AppCompat.Light` 107 | 2. Material: Drawer *covers* App bar (using the Toolbar) 108 | * use `Theme.AppCompat.NoActionBar` or `Theme.AppCompat.Light.NoActionBar` 109 | * add toolbar padding 110 | 111 | 112 | * Using Drawer for Navigation 113 | * This module only provides the layout itself. The Navigation logic must be done in your own code. 114 | * I've put together an example app to demonstrate this here: [NavigationDrawer Demo App](https://github.com/manumaticx/NavigationDrawer-Demo) 115 | 116 | 117 | * Customizing the drawerArrowToggle 118 | * This is done in your ActionBar theme like this: 119 | 120 | ```xml 121 | 124 | 125 | 129 | ``` 130 | 131 | Android Docs: http://developer.android.com/reference/android/support/v7/appcompat/R.styleable.html#DrawerArrowToggle 132 | 133 | * TabGroup & Drawer 134 | * Please refer to my answer [here](https://github.com/manumaticx/Ti.DrawerLayout/issues/32#issuecomment-111413941) 135 | -------------------------------------------------------------------------------- /example/app.js: -------------------------------------------------------------------------------- 1 | // This is a test harness for your module 2 | // You should do something interesting in this harness 3 | // to test out the module and to provide instructions 4 | // to users on how to use it by example. 5 | 6 | 7 | // open a single window 8 | var TiDrawerLayout = require('com.tripvi.drawerlayout'); 9 | 10 | var win = Ti.UI.createWindow({ 11 | backgroundColor: 'white', 12 | }); 13 | 14 | var menuTable = Ti.UI.createTableView({ 15 | data: [ 16 | { title: "menu A" }, 17 | { title: "menu B" }, 18 | { title: "menu C" }, 19 | { title: "menu D" }, 20 | { title: "menu E" }, 21 | { title: "menu F" }, 22 | { title: "menu A" }, 23 | { title: "menu B" }, 24 | { title: "menu C" }, 25 | { title: "menu D" }, 26 | { title: "menu E" }, 27 | { title: "menu F" }, 28 | { title: "menu A" }, 29 | { title: "menu B" }, 30 | { title: "menu C" }, 31 | { title: "menu D" }, 32 | { title: "menu E" }, 33 | { title: "menu F" }, 34 | { title: "menu A" }, 35 | { title: "menu B" }, 36 | { title: "menu C" }, 37 | { title: "menu D" }, 38 | { title: "menu E" }, 39 | { title: "menu F" }, 40 | { title: "menu A" }, 41 | { title: "menu B" }, 42 | { title: "menu C" }, 43 | { title: "menu D" }, 44 | { title: "menu E" }, 45 | { title: "menu F" }, 46 | { title: "menu A" }, 47 | { title: "menu B" }, 48 | { title: "menu C" }, 49 | { title: "menu D" }, 50 | { title: "menu E" }, 51 | { title: "menu F" }, 52 | ], 53 | backgroundColor: "#ddd", 54 | }); 55 | menuTable.addEventListener("click", function(ev) { 56 | var cv = Ti.UI.createView({ 57 | backgroundColor: 'orange', 58 | }); 59 | drawer.centerView = cv; 60 | win.title = "ROW " + ev.index; 61 | drawer.closeLeftWindow(); 62 | }); 63 | 64 | var contentView = Ti.UI.createScrollView({ 65 | backgroundColor: "#fff", 66 | layout: "vertical", 67 | }); 68 | 69 | var title = Ti.UI.createLabel({ 70 | top: "25dp", 71 | text: "Main Content View", 72 | font: { 73 | fontSize: 24, 74 | }, 75 | color: "#000", 76 | }); 77 | contentView.add(title); 78 | 79 | var changeDrawerWidthButton = Ti.UI.createButton({ 80 | top: "25dp", 81 | title: "drawer width: 120", 82 | }); 83 | changeDrawerWidthButton.addEventListener("click", function(e) { 84 | drawer.leftDrawerWidth = "120dp"; 85 | }); 86 | contentView.add(changeDrawerWidthButton); 87 | 88 | var openNewWindowButton = Ti.UI.createButton({ 89 | top: "75dp", 90 | title: "open new window", 91 | }); 92 | openNewWindowButton.addEventListener("click", function(e) { 93 | var w = Ti.UI.createWindow({ 94 | backgroundColor: 'orange', 95 | title: "COOL" 96 | }); 97 | w.addEventListener('open', function() { 98 | w.activity.actionBar.logo = ""; 99 | w.activity.actionBar.displayHomeAsUp = true; 100 | w.activity.actionBar.subtitle = "hello actionBar"; 101 | }); 102 | w.open(); 103 | }); 104 | contentView.add(openNewWindowButton); 105 | 106 | var enableRightDrawerButton = Ti.UI.createButton({ 107 | top: "125dp", 108 | title: "enable right drawer", 109 | }); 110 | enableRightDrawerButton.addEventListener("click", function(e) { 111 | var rv = Ti.UI.createView({ 112 | backgroundColor: "#def" 113 | }); 114 | 115 | var caption = Ti.UI.createLabel({ 116 | text: "Filter", 117 | font: { 118 | fontSize: 24, 119 | fontWeight: 'bold', 120 | }, 121 | color: "#000", 122 | }); 123 | rv.add(caption); 124 | 125 | drawer.rightView = rv; 126 | }); 127 | contentView.add(enableRightDrawerButton); 128 | 129 | 130 | var drawer = TiDrawerLayout.createDrawer({ 131 | leftView: menuTable, 132 | centerView: contentView 133 | //drawerLockMode:TiDrawerLayout.LOCK_MODE_LOCKED_CLOSED, // prevents user from swiping. manual use of toggleLeftWindow() still works 134 | //drawerIndicatorEnabled: false 135 | }); 136 | drawer.addEventListener('draweropen', function(e) { 137 | win.title = "open " + e.drawer; 138 | }); 139 | drawer.addEventListener('drawerclose', function(e) { 140 | win.title = "close"; 141 | }); 142 | drawer.addEventListener('drawerslide', function(e) { 143 | win.title = "slide: " + e.offset.toFixed(2); 144 | }); 145 | 146 | win.addEventListener("open", function() { 147 | win.activity.actionBar.onHomeIconItemSelected = function() { 148 | drawer.toggleLeftWindow(); 149 | }; 150 | }); 151 | 152 | win.add(drawer); 153 | win.open(); 154 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "drawerlayout", 3 | "id": "com.tripvi.drawerlayout", 4 | "version": "3.0.1", 5 | "description": "Android Drawer for Titanium ", 6 | "license": "MIT", 7 | "devDependencies": { 8 | "grunt": "~0.4.5" 9 | } 10 | } 11 | --------------------------------------------------------------------------------