blob: 2588a8156b0018d6c329548eb11e307e59773d88 [file] [log] [blame]
/*
* 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);
}
}