| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.support.car.app.menu; |
| |
| import android.content.Context; |
| import android.graphics.Bitmap; |
| import android.graphics.drawable.Drawable; |
| import android.os.Bundle; |
| import android.os.Handler; |
| import android.support.annotation.LayoutRes; |
| import android.support.car.Car; |
| import android.support.car.app.CarFragmentActivity; |
| import android.support.car.app.menu.compat.CarMenuConstantsComapt.MenuItemConstants; |
| import android.support.car.input.CarInputManager; |
| import android.support.v4.app.Fragment; |
| import android.util.DisplayMetrics; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.view.WindowManager; |
| import android.widget.EditText; |
| |
| /** |
| * Base class for a car app which wants to use a drawer. |
| * @hide |
| */ |
| public abstract class CarDrawerActivity extends CarFragmentActivity { |
| private static final String TAG = "CarDrawerActivity"; |
| |
| private static final String KEY_DRAWERSHOWING = |
| "android.support.car.app.CarDrawerActivity.DRAWER_SHOWING"; |
| private static final String KEY_INPUTSHOWING = |
| "android.support.car.app.CarDrawerActivity.INPUT_SHOWING"; |
| private static final String KEY_SEARCHBOXENABLED = |
| "android.support.car.app.CarDrawerActivity.SEARCH_BOX_ENABLED"; |
| |
| private final Handler mHandler = new Handler(); |
| private final CarUiController mUiController; |
| |
| private CarMenuCallbacks mMenuCallbacks; |
| private OnMenuClickListener mMenuClickListener; |
| private boolean mDrawerShowing; |
| private boolean mShowingSearchBox; |
| private boolean mSearchBoxEnabled; |
| private boolean mOnCreateCalled = false; |
| private View.OnClickListener mSearchBoxOnClickListener; |
| |
| private CarInputManager mInputManager; |
| private EditText mSearchBoxView; |
| |
| public interface OnMenuClickListener { |
| /** |
| * Called when the menu button is clicked. |
| * |
| * @return True if event was handled. This will prevent the drawer from executing its |
| * default action (opening/closing/going back). False if the event was not handled |
| * so the drawer will execute the default action. |
| */ |
| boolean onClicked(); |
| } |
| |
| public CarDrawerActivity(Proxy proxy, Context context, Car car) { |
| super(proxy, context, car); |
| mUiController = createCarUiController(); |
| } |
| |
| /** |
| * Create a {@link android.support.car.app.menu.CarUiController}. |
| * |
| * Derived class can override this function to return a customized ui controller. |
| */ |
| protected CarUiController createCarUiController() { |
| return CarUiController.createCarUiController(this); |
| } |
| |
| @Override |
| public void setContentView(View view) { |
| ViewGroup parent = (ViewGroup) findViewById(mUiController.getFragmentContainerId()); |
| parent.addView(view); |
| } |
| |
| @Override |
| public void setContentView(@LayoutRes int resourceId) { |
| ViewGroup parent = (ViewGroup) findViewById(mUiController.getFragmentContainerId()); |
| LayoutInflater inflater = getLayoutInflater(); |
| inflater.inflate(resourceId, parent, true); |
| } |
| |
| @Override |
| public View findViewById(@LayoutRes int id) { |
| return super.findViewById(mUiController.getFragmentContainerId()).findViewById(id); |
| } |
| |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| super.setContentView(mUiController.getContentView()); |
| mInputManager = getInputManager(); |
| mHandler.post(new Runnable() { |
| @Override |
| public void run() { |
| if (mMenuCallbacks != null) { |
| mMenuCallbacks.registerOnChildrenChangedListener(mMenuListener); |
| } |
| mOnCreateCalled = true; |
| } |
| }); |
| } |
| |
| @Override |
| protected void onDestroy() { |
| super.onDestroy(); |
| mHandler.post(new Runnable() { |
| @Override |
| public void run() { |
| if (mMenuCallbacks != null) { |
| mMenuCallbacks.unregisterOnChildrenChangedListener(mMenuListener); |
| mMenuCallbacks = null; |
| } |
| } |
| }); |
| } |
| |
| @Override |
| protected void onRestoreInstanceState(Bundle savedInstanceState) { |
| super.onRestoreInstanceState(savedInstanceState); |
| mDrawerShowing = savedInstanceState.getBoolean(KEY_DRAWERSHOWING); |
| mUiController.onRestoreInstanceState(savedInstanceState); |
| } |
| |
| @Override |
| protected void onSaveInstanceState(Bundle outState) { |
| super.onSaveInstanceState(outState); |
| outState.putBoolean(KEY_DRAWERSHOWING, mDrawerShowing); |
| mUiController.onSaveInstanceState(outState); |
| } |
| |
| @Override |
| protected void onStart() { |
| super.onStart(); |
| getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); |
| mUiController.onStart(); |
| } |
| |
| @Override |
| protected void onResume() { |
| super.onResume(); |
| mUiController.onResume(); |
| } |
| |
| @Override |
| protected void onPause() { |
| super.onPause(); |
| mUiController.onPause(); |
| } |
| |
| @Override |
| protected void onStop() { |
| super.onStop(); |
| mUiController.onStop(); |
| } |
| |
| /** |
| * Set the fragment in the main fragment container. |
| */ |
| public void setContentFragment(Fragment fragment) { |
| super.setContentFragment(fragment, mUiController.getFragmentContainerId()); |
| } |
| |
| /** |
| * Return the main fragment container id for the app. |
| */ |
| public int getFragmentContainerId() { |
| return mUiController.getFragmentContainerId(); |
| } |
| |
| /** |
| * Set the callbacks for car menu interactions. |
| */ |
| public void setCarMenuCallbacks(final CarMenuCallbacks callbacks) { |
| if (mOnCreateCalled) { |
| throw new IllegalStateException( |
| "Cannot call setCarMenuCallbacks after onCreate has been called."); |
| } |
| mMenuCallbacks = callbacks; |
| mUiController.registerCarMenuCallbacks(callbacks); |
| } |
| |
| /** |
| * Listener that listens for when the menu button is pressed. |
| * |
| * @param listener {@link OnMenuClickListener} that will listen for menu button clicks. |
| */ |
| public void setOnMenuClickedListener(OnMenuClickListener listener) { |
| mMenuClickListener = listener; |
| } |
| |
| /** |
| * Restore the menu button drawable |
| */ |
| public void restoreMenuButtonDrawable() { |
| mUiController.restoreMenuButtonDrawable(); |
| } |
| |
| /** |
| * Sets the menu button bitmap |
| * |
| * @param bitmap Bitmap to the menu button to. |
| */ |
| public void setMenuButtonBitmap(Bitmap bitmap) { |
| mUiController.setMenuButtonBitmap(bitmap); |
| } |
| |
| /** |
| * Set the title of the menu. |
| */ |
| public void setTitle(CharSequence title) { |
| mUiController.setTitle(title); |
| } |
| |
| /** |
| * Set the System UI to be light. |
| */ |
| public void setLightMode() { |
| mUiController.setLightMode(); |
| } |
| |
| /** |
| * Set the System UI to be dark. |
| */ |
| public void setDarkMode() { |
| mUiController.setDarkMode(); |
| } |
| |
| /** |
| * Set the System UI to be dark during day mode and light during night mode. |
| */ |
| public void setAutoLightDarkMode() { |
| mUiController.setAutoLightDarkMode(); |
| } |
| |
| /** |
| * Sets the application background to the given {@link android.graphics.Bitmap}. |
| * |
| * @param bitmap to use as background. |
| */ |
| public void setBackground(Bitmap bitmap) { |
| mUiController.setBackground(bitmap); |
| } |
| |
| /** |
| * Sets the color of the scrim to the right of the car menu drawer. |
| */ |
| public void setScrimColor(int color) { |
| mUiController.setScrimColor(color); |
| } |
| |
| /** |
| * Show the menu associated with the given id in the drawer. |
| * |
| * @param id Id of the menu to link to. |
| * @param title Title that should be displayed. |
| */ |
| public void showMenu(String id, String title) { |
| mUiController.showMenu(id, title); |
| } |
| |
| public boolean onMenuClicked() { |
| if (mMenuClickListener != null) { |
| return mMenuClickListener.onClicked(); |
| } |
| return false; |
| } |
| |
| public void restoreSearchBox() { |
| if (isSearchBoxEnabled()) { |
| mUiController.showSearchBox(mSearchBoxOnClickListener); |
| mShowingSearchBox = true; |
| } |
| } |
| |
| private final CarMenuCallbacks.OnChildrenChangedListener mMenuListener = |
| new CarMenuCallbacks.OnChildrenChangedListener() { |
| @Override |
| public void onChildrenChanged(String parentId) { |
| if (mOnCreateCalled) { |
| mUiController.onChildrenChanged(parentId); |
| } |
| } |
| |
| @Override |
| public void onChildChanged(String parentId, Bundle item, |
| Drawable leftIcon, Drawable rightIcon) { |
| DisplayMetrics metrics = getResources().getDisplayMetrics(); |
| if (leftIcon != null) { |
| item.putParcelable(MenuItemConstants.KEY_LEFTICON, |
| Utils.snapshot(metrics, leftIcon)); |
| } |
| |
| if (rightIcon != null) { |
| item.putParcelable(MenuItemConstants.KEY_RIGHTICON, |
| Utils.snapshot(metrics, rightIcon)); |
| } |
| if (mOnCreateCalled) { |
| mUiController.onChildChanged(parentId, item); |
| } |
| } |
| }; |
| |
| public void closeDrawer() { |
| mUiController.closeDrawer(); |
| } |
| |
| public void openDrawer() { |
| mUiController.openDrawer(); |
| } |
| |
| public boolean isDrawerShowing() { |
| return mDrawerShowing; |
| } |
| |
| public void setDrawerShowing(boolean showing) { |
| mDrawerShowing = showing; |
| } |
| |
| public boolean isSearchBoxEnabled() { |
| return mSearchBoxEnabled; |
| } |
| |
| public boolean isShowingSearchBox() { |
| return mShowingSearchBox; |
| } |
| |
| /** |
| * Shows a small clickable {@link android.widget.EditText}. |
| * |
| * {@link View} will be {@code null} in {@link View.OnClickListener#onClick(View)}. |
| * |
| * @param listener {@link View.OnClickListener} that is called when user selects the |
| * {@link android.widget.EditText}. |
| */ |
| public void showSearchBox(View.OnClickListener listener) { |
| if (!isDrawerShowing()) { |
| mUiController.showSearchBox(listener); |
| mShowingSearchBox = true; |
| } |
| mSearchBoxEnabled = true; |
| mSearchBoxOnClickListener = listener; |
| } |
| |
| public void showSearchBox() { |
| showSearchBox(mSearchBoxOnClickListener); |
| } |
| |
| public void hideSearchBox() { |
| if (isShowingSearchBox()) { |
| stopInput(); |
| } |
| mSearchBoxEnabled = false; |
| } |
| |
| public void setSearchBoxEditListener(SearchBoxEditListener listener) { |
| mUiController.setSearchBoxEditListener(listener); |
| } |
| |
| public void stopInput() { |
| // STOPSHIP: sometimes focus is lost and we are not able to hide the keyboard. |
| // properly fix this before we ship. |
| if (mSearchBoxView != null) { |
| mSearchBoxView.requestFocusFromTouch(); |
| } |
| mUiController.stopInput(); |
| mInputManager.stopInput(); |
| mShowingSearchBox = false; |
| } |
| |
| /** |
| * Start input on the search box that is provided by a car ui provider. |
| * TODO: Migrate to use the new input/search api once it becomes stable (b/27108311). |
| * @param hint Search hint |
| */ |
| public void startInput(String hint) { |
| startInput(hint, mSearchBoxOnClickListener); |
| } |
| |
| /** |
| * Start input on the search box that is provided by a car ui provider. |
| * TODO: Migrate to use the new input/search api once it becomes stable (b/27108311). |
| * @param hint Search hint |
| * @param onClickListener Listener for the search box clicks. |
| */ |
| public void startInput(final String hint, final View.OnClickListener onClickListener) { |
| mInputManager = getInputManager(); |
| EditText inputView = mUiController.startInput(hint, onClickListener); |
| getInputManager().startInput(inputView); |
| mSearchBoxView = inputView; |
| mShowingSearchBox = true; |
| } |
| |
| public void setSearchBoxColors(int backgroundColor, int searchLogoColor, int textColor, |
| int hintTextColor) { |
| mUiController.setSearchBoxColors(backgroundColor, searchLogoColor, |
| textColor, hintTextColor); |
| } |
| |
| public void setSearchBoxEndView(View endView) { |
| mUiController.setSearchBoxEndView(endView); |
| } |
| |
| public void showToast(String text, int duration) { |
| mUiController.showToast(text, duration); |
| } |
| } |