Java tutorial
/** * Appcelerator Titanium Mobile * Copyright (c) 2017 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ package ti.modules.titanium.ui.widget; import ti.modules.titanium.ui.android.DrawerLayoutProxy; import ti.modules.titanium.ui.WindowProxy; import org.appcelerator.kroll.KrollDict; import org.appcelerator.kroll.KrollProxy; import org.appcelerator.titanium.TiDimension; import org.appcelerator.titanium.TiC; import org.appcelerator.titanium.proxy.TiViewProxy; import org.appcelerator.titanium.util.TiConvert; import org.appcelerator.titanium.util.TiRHelper; import org.appcelerator.titanium.util.TiRHelper.ResourceNotFoundException; import org.appcelerator.titanium.view.TiCompositeLayout; import org.appcelerator.titanium.view.TiUIView; import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.DrawerLayout.LayoutParams; import android.support.v4.widget.ViewDragHelper; import android.support.v7.app.AppCompatActivity; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.widget.FrameLayout; import android.widget.RelativeLayout; import java.lang.reflect.Field; public class TiUIDrawerLayout extends TiUIView { private DrawerLayout layout = null; private ActionBarDrawerToggle drawerToggle = null; private FrameLayout leftFrame = null; private FrameLayout rightFrame = null; private int leftWidth; private int rightWidth; private Toolbar toolbar; private boolean toolbarEnabled = false; private TiViewProxy leftView; private TiViewProxy rightView; private TiViewProxy centerView; private static final String TAG = "TiUIDrawerLayout"; static int id_drawer_open_string = 0; static int id_drawer_close_string = 0; static int id_drawer_layout = 0; static int id_drawer_layout_container = 0; static int id_toolbar = 0; public TiUIDrawerLayout(final DrawerLayoutProxy proxy) { super(proxy); try { if (id_drawer_open_string == 0) { id_drawer_open_string = TiRHelper.getResource("string.drawer_layout_open"); } if (id_drawer_close_string == 0) { id_drawer_close_string = TiRHelper.getResource("string.drawer_layout_close"); } if (id_drawer_layout == 0) { id_drawer_layout = TiRHelper.getResource("layout.titanium_ui_drawer_layout"); } if (id_drawer_layout_container == 0) { id_drawer_layout_container = TiRHelper.getResource("id.drawer_layout_container"); } if (id_toolbar == 0) { id_toolbar = TiRHelper.getResource("id.drawer_layout_toolbar"); } } catch (ResourceNotFoundException e) { Log.e(TAG, "XML resources could not be found!!!"); } AppCompatActivity activity = (AppCompatActivity) proxy.getActivity(); LayoutInflater inflater = LayoutInflater.from(activity); layout = (DrawerLayout) inflater.inflate(id_drawer_layout, null, false); layout.setDrawerListener(new DrawerListener()); toolbar = (Toolbar) layout.findViewById(id_toolbar); if (activity.getSupportActionBar() == null && activity.getActionBar() == null) { activity.setSupportActionBar(toolbar); if (!toolbarEnabled) { toolbarEnabled = true; setToolbarVisible(toolbarEnabled); } } setNativeView(layout); } private void setToolbarVisible(boolean visible) { if (visible) { toolbar.setVisibility(View.VISIBLE); } else { toolbar.setVisibility(View.GONE); } } private void drawerClosedEvent(View drawerView) { if (proxy.hasListeners(TiC.EVENT_CLOSE)) { KrollDict options = new KrollDict(); if (drawerView.equals(leftFrame)) { options.put("drawer", "left"); } else if (drawerView.equals(rightFrame)) { options.put("drawer", "right"); } proxy.fireEvent(TiC.EVENT_CLOSE, options); } } private void drawerOpenedEvent(View drawerView) { if (proxy.hasListeners(TiC.EVENT_OPEN)) { KrollDict options = new KrollDict(); if (drawerView.equals(leftFrame)) { options.put("drawer", "left"); } else if (drawerView.equals(rightFrame)) { options.put("drawer", "right"); } proxy.fireEvent(TiC.EVENT_OPEN, options); } } private void drawerStateChangedEvent(int state) { if (proxy.hasListeners(TiC.EVENT_CHANGE)) { KrollDict options = new KrollDict(); options.put("state", state); options.put("idle", (state == DrawerLayout.STATE_IDLE)); options.put("dragging", (state == DrawerLayout.STATE_DRAGGING)); options.put("settling", (state == DrawerLayout.STATE_SETTLING)); proxy.fireEvent(TiC.EVENT_CHANGE, options); } } private void drawerSlideEvent(View drawerView, float slideOffset) { if (proxy.hasListeners(TiC.EVENT_SLIDE)) { KrollDict options = new KrollDict(); options.put("offset", slideOffset); if (drawerView.equals(leftFrame)) { options.put("drawer", "left"); } else if (drawerView.equals(rightFrame)) { options.put("drawer", "right"); } proxy.fireEvent(TiC.EVENT_SLIDE, options); } } private class DrawerListener implements DrawerLayout.DrawerListener { @Override public void onDrawerClosed(View drawerView) { drawerClosedEvent(drawerView); } @Override public void onDrawerOpened(View drawerView) { drawerOpenedEvent(drawerView); } @Override public void onDrawerSlide(View drawerView, float slideOffset) { drawerSlideEvent(drawerView, slideOffset); } @Override public void onDrawerStateChanged(int state) { drawerStateChangedEvent(state); } } public void toggleLeft() { if (layout.isDrawerOpen(Gravity.START)) { closeLeft(); } else { openLeft(); } } public void openLeft() { layout.openDrawer(Gravity.START); } public void closeLeft() { layout.closeDrawer(Gravity.START); } public void toggleRight() { if (layout.isDrawerOpen(Gravity.END)) { closeRight(); } else { openRight(); } } public void openRight() { layout.openDrawer(Gravity.END); } public void closeRight() { layout.closeDrawer(Gravity.END); } public boolean isLeftOpen() { return layout.isDrawerOpen(Gravity.START); } public boolean isRightOpen() { return layout.isDrawerOpen(Gravity.END); } public boolean isLeftVisible() { return layout.isDrawerVisible(Gravity.START); } public boolean isRightVisible() { return layout.isDrawerVisible(Gravity.END); } private void initDrawerToggle() { AppCompatActivity activity = (AppCompatActivity) proxy.getActivity(); if (activity.getSupportActionBar() == null) { return; } activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true); activity.getSupportActionBar().setHomeButtonEnabled(true); drawerToggle = new ActionBarDrawerToggle(activity, layout, id_drawer_open_string, id_drawer_close_string) { @Override public void onDrawerClosed(View drawerView) { drawerClosedEvent(drawerView); } @Override public void onDrawerOpened(View drawerView) { drawerOpenedEvent(drawerView); } @Override public void onDrawerSlide(View drawerView, float slideOffset) { drawerSlideEvent(drawerView, slideOffset); } @Override public void onDrawerStateChanged(int state) { drawerStateChangedEvent(state); } }; layout.setDrawerListener(drawerToggle); layout.post(new Runnable() { @Override public void run() { drawerToggle.syncState(); } }); } private void initLeft() { if (leftFrame != null) { return; } leftFrame = new FrameLayout(proxy.getActivity()); LayoutParams frameLayout = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); frameLayout.gravity = Gravity.START; leftFrame.setLayoutParams(frameLayout); layout.addView(leftFrame); if (drawerToggle == null) { initDrawerToggle(); } } private void initRight() { if (rightFrame != null) { return; } rightFrame = new FrameLayout(proxy.getActivity()); LayoutParams frameLayout = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); frameLayout.gravity = Gravity.END; rightFrame.setLayoutParams(frameLayout); layout.addView(rightFrame); } public void setCenterView(TiViewProxy viewProxy) { if (viewProxy == null || viewProxy == this.centerView) { return; } viewProxy.setActivity(proxy.getActivity()); TiUIView contentView = viewProxy.getOrCreateView(); View view = contentView.getOuterView(); RelativeLayout container = (RelativeLayout) layout.findViewById(id_drawer_layout_container); TiCompositeLayout content = (TiCompositeLayout) container.getChildAt(1); ViewParent viewParent = view.getParent(); if (viewParent != null && viewParent != content && viewParent instanceof ViewGroup) { ((ViewGroup) viewParent).removeView(view); } content.addView(view, contentView.getLayoutParams()); if (this.centerView != null) { content.removeView(this.centerView.getOrCreateView().getNativeView()); } this.centerView = viewProxy; } private void setDrawMargin(Integer width) { try { Field mDragger = layout.getClass().getDeclaredField("mLeftDragger"); mDragger.setAccessible(true); ViewDragHelper draggerObj = (ViewDragHelper) mDragger.get(layout); Field mEdgeSize = draggerObj.getClass().getDeclaredField("mEdgeSize"); mEdgeSize.setAccessible(true); mEdgeSize.setInt(draggerObj, width); } catch (NoSuchFieldException e) { Log.e(TAG, e.toString()); } catch (IllegalAccessException e) { Log.e(TAG, e.toString()); } } @Override public void processProperties(KrollDict d) { if (d.containsKey(TiC.PROPERTY_LEFT_VIEW)) { Object leftView = d.get(TiC.PROPERTY_LEFT_VIEW); if (leftView != null && leftView instanceof TiViewProxy) { if (leftView instanceof WindowProxy) { throw new IllegalStateException("cannot add window as a child view of other window"); } this.leftView = (TiViewProxy) leftView; this.initLeft(); this.leftFrame.addView(getNativeView(this.leftView)); } else { Log.e(TAG, "invalid type for leftView"); } } if (d.containsKey(TiC.PROPERTY_RIGHT_VIEW)) { Object rightView = d.get(TiC.PROPERTY_RIGHT_VIEW); if (rightView != null && rightView instanceof TiViewProxy) { if (rightView instanceof WindowProxy) { throw new IllegalStateException("cannot add window as a child view of other window"); } this.rightView = (TiViewProxy) rightView; this.initRight(); this.rightFrame.addView(getNativeView(this.rightView)); } else { Log.e(TAG, "invalid type for rightView"); } } if (d.containsKey(TiC.PROPERTY_CENTER_VIEW)) { Object centerView = d.get(TiC.PROPERTY_CENTER_VIEW); if (centerView != null && centerView instanceof TiViewProxy) { if (centerView instanceof WindowProxy) { throw new IllegalStateException("cannot use window as a child view of other window"); } setCenterView((TiViewProxy) centerView); } else { Log.e(TAG, "invalid type for centerView"); } } if (d.containsKey(TiC.PROPERTY_LEFT_WIDTH)) { if (leftFrame != null) { if (d.get(TiC.PROPERTY_LEFT_WIDTH).equals(TiC.LAYOUT_SIZE)) { leftFrame.getLayoutParams().width = LayoutParams.WRAP_CONTENT; } else if (d.get(TiC.PROPERTY_LEFT_WIDTH).equals(TiC.LAYOUT_FILL)) { leftFrame.getLayoutParams().width = LayoutParams.MATCH_PARENT; } else if (!d.get(TiC.PROPERTY_LEFT_WIDTH).equals(TiC.SIZE_AUTO)) { leftWidth = getDevicePixels(d.get(TiC.PROPERTY_LEFT_WIDTH)); leftFrame.getLayoutParams().width = leftWidth; } } } else { if (leftFrame != null) { leftFrame.getLayoutParams().width = LayoutParams.MATCH_PARENT; } } if (d.containsKey(TiC.PROPERTY_RIGHT_WIDTH)) { if (rightFrame != null) { if (d.get(TiC.PROPERTY_RIGHT_WIDTH).equals(TiC.LAYOUT_SIZE)) { rightFrame.getLayoutParams().width = LayoutParams.WRAP_CONTENT; } else if (d.get(TiC.PROPERTY_RIGHT_WIDTH).equals(TiC.LAYOUT_FILL)) { rightFrame.getLayoutParams().width = LayoutParams.MATCH_PARENT; } else if (!d.get(TiC.PROPERTY_RIGHT_WIDTH).equals(TiC.SIZE_AUTO)) { rightWidth = getDevicePixels(d.get(TiC.PROPERTY_RIGHT_WIDTH)); rightFrame.getLayoutParams().width = rightWidth; } } } else { if (rightFrame != null) { rightFrame.getLayoutParams().width = LayoutParams.MATCH_PARENT; } } if (d.containsKey(TiC.PROPERTY_DRAWER_LOCK_MODE)) { layout.setDrawerLockMode(TiConvert.toInt(d.get(TiC.PROPERTY_DRAWER_LOCK_MODE))); } if (d.containsKey(TiC.PROPERTY_TOOLBAR_ENABLED)) { toolbarEnabled = TiConvert.toBoolean(d.get(TiC.PROPERTY_TOOLBAR_ENABLED)); setToolbarVisible(toolbarEnabled); } if (d.containsKey(TiC.PROPERTY_DRAG_MARGIN)) { setDrawMargin(getDevicePixels(d.get(TiC.PROPERTY_DRAG_MARGIN))); } super.processProperties(d); } @Override public void propertyChanged(String key, Object oldValue, Object newValue, KrollProxy proxy) { if (key.equals(TiC.PROPERTY_LEFT_VIEW)) { if (newValue == null || newValue == this.leftView) { return; } TiViewProxy newProxy = null; int index = 0; if (this.leftView != null) { index = this.leftFrame.indexOfChild(this.leftView.getOrCreateView().getNativeView()); } if (newValue instanceof TiViewProxy) { if (newValue instanceof WindowProxy) { throw new IllegalStateException("cannot add window as a child view of other window"); } newProxy = (TiViewProxy) newValue; initLeft(); this.leftFrame.addView(newProxy.getOrCreateView().getOuterView(), index); } else { Log.e(TAG, "invalid type for leftView"); } if (this.leftView != null) { this.leftFrame.removeView(this.leftView.getOrCreateView().getNativeView()); } this.leftView = newProxy; } else if (key.equals(TiC.PROPERTY_RIGHT_VIEW)) { if (newValue == null || newValue == this.rightView) { return; } TiViewProxy newProxy = null; int index = 0; if (this.rightView != null) { index = this.rightFrame.indexOfChild(this.rightView.getOrCreateView().getNativeView()); } if (newValue instanceof TiViewProxy) { if (newValue instanceof WindowProxy) { throw new IllegalStateException("cannot add window as a child view of other window"); } newProxy = (TiViewProxy) newValue; initRight(); this.rightFrame.addView(newProxy.getOrCreateView().getOuterView(), index); } else { Log.e(TAG, "invalid type for rightView"); } if (this.rightView != null) { this.rightFrame.removeView(this.rightView.getOrCreateView().getNativeView()); } this.rightView = newProxy; } else if (key.equals(TiC.PROPERTY_CENTER_VIEW)) { TiViewProxy newProxy = (TiViewProxy) newValue; setCenterView(newProxy); } else if (key.equals(TiC.PROPERTY_LEFT_WIDTH)) { if (leftFrame == null) { return; } initLeft(); if (newValue.equals(TiC.LAYOUT_SIZE)) { leftWidth = LayoutParams.WRAP_CONTENT; } else if (newValue.equals(TiC.LAYOUT_FILL)) { leftWidth = LayoutParams.MATCH_PARENT; } else if (!newValue.equals(TiC.SIZE_AUTO)) { leftWidth = getDevicePixels(newValue); } LayoutParams leftFrameLayout = new LayoutParams(leftWidth, LayoutParams.MATCH_PARENT); leftFrameLayout.gravity = Gravity.START; this.leftFrame.setLayoutParams(leftFrameLayout); } else if (key.equals(TiC.PROPERTY_RIGHT_WIDTH)) { if (rightFrame == null) { return; } initRight(); if (newValue.equals(TiC.LAYOUT_SIZE)) { rightWidth = LayoutParams.WRAP_CONTENT; } else if (newValue.equals(TiC.LAYOUT_FILL)) { rightWidth = LayoutParams.MATCH_PARENT; } else if (!newValue.equals(TiC.SIZE_AUTO)) { rightWidth = getDevicePixels(newValue); } LayoutParams rightFrameLayout = new LayoutParams(rightWidth, LayoutParams.MATCH_PARENT); rightFrameLayout.gravity = Gravity.END; this.rightFrame.setLayoutParams(rightFrameLayout); } else if (key.equals(TiC.PROPERTY_DRAWER_LOCK_MODE)) { layout.setDrawerLockMode(TiConvert.toInt(newValue)); } else if (key.equals(TiC.PROPERTY_DRAWER_INDICATOR_ENABLED)) { if (drawerToggle != null) { drawerToggle.setDrawerIndicatorEnabled((Boolean) newValue); } } else if (key.equals(TiC.PROPERTY_TOOLBAR_ENABLED)) { toolbarEnabled = TiConvert.toBoolean(newValue); setToolbarVisible(toolbarEnabled); } else if (key.equals(TiC.PROPERTY_DRAG_MARGIN)) { setDrawMargin(getDevicePixels(newValue)); } else { super.propertyChanged(key, oldValue, newValue, proxy); } } @Override public void release() { if (layout != null) { layout.removeAllViews(); layout.setDrawerListener(null); layout = null; } if (leftFrame != null) { leftFrame.removeAllViews(); leftFrame = null; } if (rightFrame != null) { rightFrame.removeAllViews(); rightFrame = null; } if (leftView != null) { leftView.releaseViews(); leftView = null; } if (rightView != null) { rightView.releaseViews(); rightView = null; } if (centerView != null) { centerView.releaseViews(); centerView = null; } if (toolbar != null) { toolbar.removeAllViews(); toolbar = null; } super.release(); proxy = null; } private int getDevicePixels(Object value) { TiDimension nativeSize = TiConvert.toTiDimension(TiConvert.toString(value), TiDimension.TYPE_WIDTH); return nativeSize.getAsPixels(layout); } private View getNativeView(TiViewProxy viewProxy) { View nativeView = viewProxy.getOrCreateView().getOuterView(); ViewGroup parentViewGroup = (ViewGroup) nativeView.getParent(); if (parentViewGroup != null) { parentViewGroup.removeAllViews(); } return nativeView; } }