/* * Copyright 2014 Google Inc. All rights reserved. * * 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 com.google.samples.apps.iosched.ui.tablet; import android.app.ActionBar; import android.app.Fragment; import android.app.FragmentBreadCrumbs; import android.app.FragmentManager; import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.net.Uri; import android.os.Bundle; import android.view.Gravity; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import com.google.samples.apps.iosched.R; import com.google.samples.apps.iosched.model.TagMetadata; import com.google.samples.apps.iosched.provider.ScheduleContract; import com.google.samples.apps.iosched.ui.*; import com.google.samples.apps.iosched.ui.phone.MapActivity; import com.google.samples.apps.iosched.util.AnalyticsManager; import com.google.samples.apps.iosched.util.UIUtils; import static com.google.samples.apps.iosched.util.LogUtils.LOGD; /** * A multi-pane activity, where the primary navigation pane is a * {@link MapFragment}, that shows {@link SessionsFragment}, * {@link SessionDetailFragment} as popups. This activity requires API level 11 * or greater because of its use of {@link FragmentBreadCrumbs}. */ public class MapMultiPaneActivity extends NearbyActivity implements FragmentManager.OnBackStackChangedListener, MapFragment.Callbacks, SessionsFragment.Callbacks { private static final String SCREEN_LABEL = "MapMultipane"; private boolean mPauseBackStackWatcher = false; private FragmentBreadCrumbs mFragmentBreadCrumbs; private String mSelectedRoomName; private MapFragment mMapFragment; private int mActionBarOnColor; private int mActionBarOffColor; private ColorDrawable mActionBarBgDrawable; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_map); getLPreviewUtils().trySetActionBar(); FragmentManager fm = getFragmentManager(); fm.addOnBackStackChangedListener(this); mFragmentBreadCrumbs = (FragmentBreadCrumbs) findViewById(R.id.breadcrumbs); mFragmentBreadCrumbs.setActivity(this); mMapFragment = (MapFragment) fm.findFragmentByTag("map"); if (mMapFragment == null) { mMapFragment = MapFragment.newInstance(); mMapFragment.setArguments(intentToFragmentArguments(getIntent())); fm.beginTransaction() .add(R.id.fragment_container_map, mMapFragment, "map") .commit(); } findViewById(R.id.close_button).setOnClickListener(new View.OnClickListener() { public void onClick(View view) { clearBackStack(false); } }); updateBreadCrumbs(); onConfigurationChanged(getResources().getConfiguration()); /* [ANALYTICS:SCREEN] * TRIGGER: View the map screen on a tablet. * LABEL: 'MapMultipane' * [/ANALYTICS] */ AnalyticsManager.sendScreenView(SCREEN_LABEL); LOGD("Tracker", SCREEN_LABEL); overridePendingTransition(0, 0); final Resources res = getResources(); mActionBarOffColor = res.getColor(R.color.translucent_actionbar_background); mActionBarOnColor = res.getColor(R.color.theme_primary); // Initialise and set background drawable here explicitly to ensure the background // is drawn when the background color is changed on JellyBean mActionBarBgDrawable = new ColorDrawable(mActionBarOffColor); getActionBar().setBackgroundDrawable(mActionBarBgDrawable); } private void updateActionBarNavigation() { boolean show = !isNavDrawerOpen(); if (getLPreviewUtils().shouldChangeActionBarForDrawer()) { ActionBar ab = getActionBar(); ab.setDisplayShowTitleEnabled(show); ab.setDisplayUseLogoEnabled(!show); } } @Override protected void onNavDrawerStateChanged(boolean isOpen, boolean isAnimating) { super.onNavDrawerStateChanged(isOpen, isAnimating); updateActionBarNavigation(); } @Override protected void onNavDrawerSlide(float offset) { super.onNavDrawerSlide(offset); // Make Action Bar gradually fade into the theme color mActionBarBgDrawable.setColor(Color.argb( Color.alpha(mActionBarOffColor) + (int) (offset * (Color.alpha(mActionBarOnColor) - Color.alpha(mActionBarOffColor))), Color.red(mActionBarOffColor) + (int) (offset * (Color.red(mActionBarOnColor) - Color.red(mActionBarOffColor))), Color.green(mActionBarOffColor) + (int) (offset * (Color.green(mActionBarOnColor) - Color.green(mActionBarOffColor))), Color.blue(mActionBarOffColor) + (int) (offset * (Color.blue(mActionBarOnColor) - Color.blue(mActionBarOffColor))) )); getActionBar().setBackgroundDrawable(mActionBarBgDrawable); } @Override protected int getSelfNavDrawerItem() { if (getIntent().getBooleanExtra(MapActivity.EXTRA_DETACHED_MODE, false)) { // in detached mode, we don't have a nav drawer return NAVDRAWER_ITEM_INVALID; } else { return NAVDRAWER_ITEM_MAP; } } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); boolean landscape = (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE); LinearLayout spacerView = (LinearLayout) findViewById(R.id.map_detail_spacer); spacerView.setOrientation(landscape ? LinearLayout.HORIZONTAL : LinearLayout.VERTICAL); spacerView.setGravity(landscape ? Gravity.END : Gravity.BOTTOM); View popupView = findViewById(R.id.map_detail_popup); LinearLayout.LayoutParams popupLayoutParams = (LinearLayout.LayoutParams) popupView.getLayoutParams(); popupLayoutParams.width = landscape ? 0 : ViewGroup.LayoutParams.MATCH_PARENT; popupLayoutParams.height = landscape ? ViewGroup.LayoutParams.MATCH_PARENT : 0; popupLayoutParams.topMargin = getResources().getDimensionPixelSize(R.dimen.multipane_half_padding) + (landscape ? UIUtils.calculateActionBarSize(this) : 0); popupView.setLayoutParams(popupLayoutParams); popupView.requestLayout(); updateMapPadding(); } private void clearBackStack(boolean pauseWatcher) { if (pauseWatcher) { mPauseBackStackWatcher = true; } FragmentManager fm = getFragmentManager(); while (fm.getBackStackEntryCount() > 0) { fm.popBackStackImmediate(); } if (pauseWatcher) { mPauseBackStackWatcher = false; } } public void onBackStackChanged() { if (mPauseBackStackWatcher) { return; } if (getFragmentManager().getBackStackEntryCount() == 0) { showDetailPane(false); } updateBreadCrumbs(); } private void showDetailPane(boolean show) { View detailPopup = findViewById(R.id.map_detail_spacer); if (show != (detailPopup.getVisibility() == View.VISIBLE)) { detailPopup.setVisibility(show ? View.VISIBLE : View.GONE); updateMapPadding(); } } private void updateMapPadding() { // Pan the map left or up depending on the orientation. boolean landscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; boolean detailShown = findViewById(R.id.map_detail_spacer).getVisibility() == View.VISIBLE; mMapFragment.setCenterPadding( landscape ? (detailShown ? 0.25f : 0f) : 0, landscape ? 0 : (detailShown ? 0.25f : 0)); } void updateBreadCrumbs() { mFragmentBreadCrumbs.setParentTitle(null, null, null); mFragmentBreadCrumbs.setTitle(mSelectedRoomName, mSelectedRoomName); } @Override public void onSessionRoomSelected(String roomId, String roomTitle) { // We no longer have a way to display sessions that happen in a given room } @Override public void onShowPartners() { showDetailPane(true); getFragmentManager().beginTransaction() .replace(R.id.fragment_container_detail, PartnersFragment.newInstance(false)) .setBreadCrumbTitle(R.string.partners) .setBreadCrumbShortTitle(R.string.partners) .addToBackStack(null) .commit(); updateBreadCrumbs(); } @Override public void onSessionSelected(String sessionId, View clickedView) { /* [ANALYTICS:EVENT] * TRIGGER: Click on a session in the Maps screen. * CATEGORY: 'Maps' * ACTION: 'selectsession' * LABEL: session ID (for example "3284-fac320-2492048-bf391') * [/ANALYTICS] */ AnalyticsManager.sendEvent(SCREEN_LABEL, "selectsession", sessionId); getLPreviewUtils().startActivityWithTransition( new Intent(Intent.ACTION_VIEW, ScheduleContract.Sessions.buildSessionUri(sessionId)), clickedView, SessionDetailFragment.VIEW_NAME_PHOTO ); } @Override public void onTagMetadataLoaded(TagMetadata metadata) {} private void showList(Fragment fragment, Uri uri){ // Show the sessions in the room clearBackStack(true); showDetailPane(true); fragment.setArguments(BaseActivity.intentToFragmentArguments( new Intent(Intent.ACTION_VIEW, uri ))); getFragmentManager().beginTransaction() .replace(R.id.fragment_container_detail, fragment) .addToBackStack(null) .commit(); updateBreadCrumbs(); } private void showDetails(Fragment fragment, Uri uri){ // Show the session details showDetailPane(true); Intent intent = new Intent(Intent.ACTION_VIEW,uri); //intent.putExtra(SessionDetailFragment.EXTRA_VARIABLE_HEIGHT_HEADER, true); fragment.setArguments(BaseActivity.intentToFragmentArguments(intent)); getFragmentManager().beginTransaction() .replace(R.id.fragment_container_detail, fragment) .addToBackStack(null) .commit(); updateBreadCrumbs(); } // TODO: This should also update the breadcrumbs, which will likely involve a major // refactoring of the way breadcrumbs are handled. Perhaps we can store breadcrumb titles in // every back stack entry... @Override protected void showNearbyFragment(String tag) { showDetailPane(true); getFragmentManager().beginTransaction() .replace(R.id.fragment_container_detail, NearbyFragment.newInstance(false), tag) .setBreadCrumbTitle(R.string.map_nearby_button) .setBreadCrumbShortTitle(R.string.map_nearby_button) .addToBackStack(null) .commit(); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (getIntent().getBooleanExtra(MapActivity.EXTRA_DETACHED_MODE, false) && item.getItemId() == android.R.id.home) { finish(); } return super.onOptionsItemSelected(item); } }