diff options
Diffstat (limited to 'samples/SupportLeanbackDemos/src/com')
26 files changed, 2389 insertions, 52 deletions
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseErrorSupportActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseErrorSupportActivity.java new file mode 100644 index 000000000..f1e7b1e1b --- /dev/null +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseErrorSupportActivity.java @@ -0,0 +1,88 @@ +/* This file is auto-generated from BrowseErrorActivity.java. DO NOT MODIFY. */ + +/* + * Copyright (C) 2014 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 com.example.android.leanback; + +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.Fragment; +import android.os.Bundle; +import android.os.Handler; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ProgressBar; + +public class BrowseErrorSupportActivity extends FragmentActivity +{ + private ErrorSupportFragment mErrorSupportFragment; + private SpinnerSupportFragment mSpinnerSupportFragment; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.browse_support); + + testError(); + } + + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + BackgroundHelper.attach(this); + } + + @Override + public void onStop() { + BackgroundHelper.release(this); + super.onStop(); + } + + private void testError() { + mErrorSupportFragment = new ErrorSupportFragment(); + getSupportFragmentManager().beginTransaction().add(R.id.main_frame, mErrorSupportFragment).commit(); + + mSpinnerSupportFragment = new SpinnerSupportFragment(); + getSupportFragmentManager().beginTransaction().add(R.id.main_frame, mSpinnerSupportFragment).commit(); + + Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + if (getSupportFragmentManager().isDestroyed()) { + return; + } + getSupportFragmentManager().beginTransaction().remove(mSpinnerSupportFragment).commit(); + mErrorSupportFragment.setErrorContent(getResources()); + } + }, 3000); + } + + static public class SpinnerSupportFragment extends Fragment { + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + ProgressBar progressBar = new ProgressBar(container.getContext()); + if (container instanceof FrameLayout) { + FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(100, 100, Gravity.CENTER); + progressBar.setLayoutParams(layoutParams); + } + return progressBar; + } + } +} diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseFragment.java index 0a509511d..f4c8044b0 100644 --- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseFragment.java +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseFragment.java @@ -17,6 +17,7 @@ import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.support.v4.app.ActivityOptionsCompat; +import android.support.v17.leanback.app.GuidedStepFragment; import android.support.v17.leanback.widget.ArrayObjectAdapter; import android.support.v17.leanback.widget.HeaderItem; import android.support.v17.leanback.widget.ImageCardView; @@ -42,6 +43,10 @@ public class BrowseFragment extends android.support.v17.leanback.app.BrowseFragm private ArrayObjectAdapter mRowsAdapter; private BackgroundHelper mBackgroundHelper = new BackgroundHelper(); + // For good performance, it's important to use a single instance of + // a card presenter for all rows using that presenter. + final static CardPresenter sCardPresenter = new CardPresenter(); + @Override public void onCreate(Bundle savedInstanceState) { Log.i(TAG, "onCreate"); @@ -77,17 +82,18 @@ public class BrowseFragment extends android.support.v17.leanback.app.BrowseFragm } }); if (TEST_ENTRANCE_TRANSITION) { - // don't run entrance transition if Activity is restored. + // don't run entrance transition if fragment is restored. if (savedInstanceState == null) { prepareEntranceTransition(); } - // simulate delay loading data - new Handler().postDelayed(new Runnable() { - public void run() { - startEntranceTransition(); - } - }, 2000); } + // simulates in a real world use case data being loaded two seconds later + new Handler().postDelayed(new Runnable() { + public void run() { + loadData(); + startEntranceTransition(); + } + }, 2000); } private void setupRows() { @@ -100,25 +106,24 @@ public class BrowseFragment extends android.support.v17.leanback.app.BrowseFragm mRowsAdapter = new ArrayObjectAdapter(lrp); - // For good performance, it's important to use a single instance of - // a card presenter for all rows using that presenter. - final CardPresenter cardPresenter = new CardPresenter(); + setAdapter(mRowsAdapter); + } + private void loadData() { for (int i = 0; i < NUM_ROWS; ++i) { - ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter); + ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(sCardPresenter); listRowAdapter.add(new PhotoItem("Hello world", R.drawable.gallery_photo_1)); listRowAdapter.add(new PhotoItem("This is a test", "Only a test", R.drawable.gallery_photo_2)); listRowAdapter.add(new PhotoItem("Android TV", "by Google", R.drawable.gallery_photo_3)); listRowAdapter.add(new PhotoItem("Leanback", R.drawable.gallery_photo_4)); listRowAdapter.add(new PhotoItem("Hello world", R.drawable.gallery_photo_5)); - listRowAdapter.add(new PhotoItem("This is a test", "Only a test", R.drawable.gallery_photo_6)); + listRowAdapter.add(new PhotoItem("This is a test", "Open GuidedStepFragment", R.drawable.gallery_photo_6)); listRowAdapter.add(new PhotoItem("Android TV", "open RowsActivity", R.drawable.gallery_photo_7)); listRowAdapter.add(new PhotoItem("Leanback", "open BrowseActivity", R.drawable.gallery_photo_8)); HeaderItem header = new HeaderItem(i, "Row " + i); mRowsAdapter.add(new ListRow(header, listRowAdapter)); } - setAdapter(mRowsAdapter); } private final class ItemViewClickedListener implements OnItemViewClickedListener { @@ -128,7 +133,12 @@ public class BrowseFragment extends android.support.v17.leanback.app.BrowseFragm Intent intent; Bundle bundle; - if ( ((PhotoItem) item).getImageResourceId() == R.drawable.gallery_photo_8) { + if (((PhotoItem) item).getImageResourceId() == R.drawable.gallery_photo_6) { + GuidedStepFragment.add(getFragmentManager(), + new GuidedStepActivity.FirstStepFragment(), + android.R.id.content); + return; + } else if ( ((PhotoItem) item).getImageResourceId() == R.drawable.gallery_photo_8) { intent = new Intent(getActivity(), BrowseActivity.class); bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity()) .toBundle(); diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseSupportActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseSupportActivity.java new file mode 100644 index 000000000..0bafcc289 --- /dev/null +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseSupportActivity.java @@ -0,0 +1,40 @@ +/* This file is auto-generated from BrowseActivity.java. DO NOT MODIFY. */ + +/* + * Copyright (C) 2014 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 com.example.android.leanback; + +import android.support.v4.app.FragmentActivity; +import android.os.Bundle; + +public class BrowseSupportActivity extends FragmentActivity { + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.browse_support); + } + + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + BackgroundHelper.attach(this); + } + + @Override + public void onStop() { + BackgroundHelper.release(this); + super.onStop(); + } +} diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseSupportFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseSupportFragment.java new file mode 100644 index 000000000..7af875543 --- /dev/null +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/BrowseSupportFragment.java @@ -0,0 +1,162 @@ +/* This file is auto-generated from BrowseFragment.java. DO NOT MODIFY. */ + +/* + * Copyright (C) 2014 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 com.example.android.leanback; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.support.v4.app.ActivityOptionsCompat; +import android.support.v17.leanback.app.GuidedStepSupportFragment; +import android.support.v17.leanback.widget.ArrayObjectAdapter; +import android.support.v17.leanback.widget.HeaderItem; +import android.support.v17.leanback.widget.ImageCardView; +import android.support.v17.leanback.widget.ListRow; +import android.support.v17.leanback.widget.ListRowPresenter; +import android.support.v17.leanback.widget.OnItemViewClickedListener; +import android.support.v17.leanback.widget.OnItemViewSelectedListener; +import android.support.v17.leanback.widget.Presenter; +import android.support.v17.leanback.widget.Row; +import android.support.v17.leanback.widget.RowPresenter; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; + +public class BrowseSupportFragment extends android.support.v17.leanback.app.BrowseSupportFragment { + private static final String TAG = "leanback.BrowseSupportFragment"; + + private static final boolean TEST_ENTRANCE_TRANSITION = true; + private static final int NUM_ROWS = 10; + // Row heights default to wrap content + private static final boolean USE_FIXED_ROW_HEIGHT = false; + + private ArrayObjectAdapter mRowsAdapter; + private BackgroundHelper mBackgroundHelper = new BackgroundHelper(); + + // For good performance, it's important to use a single instance of + // a card presenter for all rows using that presenter. + final static CardPresenter sCardPresenter = new CardPresenter(); + + @Override + public void onCreate(Bundle savedInstanceState) { + Log.i(TAG, "onCreate"); + super.onCreate(savedInstanceState); + + setBadgeDrawable(getActivity().getResources().getDrawable(R.drawable.ic_title)); + setTitle("Leanback Sample App"); + setHeadersState(HEADERS_ENABLED); + + setOnSearchClickedListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(getActivity(), SearchSupportActivity.class); + startActivity(intent); + } + }); + + setupRows(); + setOnItemViewClickedListener(new ItemViewClickedListener()); + setOnItemViewSelectedListener(new OnItemViewSelectedListener() { + @Override + public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, + RowPresenter.ViewHolder rowViewHolder, Row row) { + Log.i(TAG, "onItemSelected: " + item + " row " + row); + + if (isShowingHeaders()) { + mBackgroundHelper.setBackground(getActivity(), null); + } + else if (item instanceof PhotoItem) { + mBackgroundHelper.setBackground( + getActivity(), ((PhotoItem) item).getImageResourceId()); + } + } + }); + if (TEST_ENTRANCE_TRANSITION) { + // don't run entrance transition if fragment is restored. + if (savedInstanceState == null) { + prepareEntranceTransition(); + } + } + // simulates in a real world use case data being loaded two seconds later + new Handler().postDelayed(new Runnable() { + public void run() { + loadData(); + startEntranceTransition(); + } + }, 2000); + } + + private void setupRows() { + ListRowPresenter lrp = new ListRowPresenter(); + + if (USE_FIXED_ROW_HEIGHT) { + lrp.setRowHeight(CardPresenter.getRowHeight(getActivity())); + lrp.setExpandedRowHeight(CardPresenter.getExpandedRowHeight(getActivity())); + } + + mRowsAdapter = new ArrayObjectAdapter(lrp); + + setAdapter(mRowsAdapter); + } + + private void loadData() { + for (int i = 0; i < NUM_ROWS; ++i) { + ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(sCardPresenter); + listRowAdapter.add(new PhotoItem("Hello world", R.drawable.gallery_photo_1)); + listRowAdapter.add(new PhotoItem("This is a test", "Only a test", R.drawable.gallery_photo_2)); + listRowAdapter.add(new PhotoItem("Android TV", "by Google", R.drawable.gallery_photo_3)); + listRowAdapter.add(new PhotoItem("Leanback", R.drawable.gallery_photo_4)); + listRowAdapter.add(new PhotoItem("Hello world", R.drawable.gallery_photo_5)); + listRowAdapter.add(new PhotoItem("This is a test", "Open GuidedStepSupportFragment", R.drawable.gallery_photo_6)); + listRowAdapter.add(new PhotoItem("Android TV", "open RowsSupportActivity", R.drawable.gallery_photo_7)); + listRowAdapter.add(new PhotoItem("Leanback", "open BrowseSupportActivity", R.drawable.gallery_photo_8)); + HeaderItem header = new HeaderItem(i, "Row " + i); + mRowsAdapter.add(new ListRow(header, listRowAdapter)); + } + + } + + private final class ItemViewClickedListener implements OnItemViewClickedListener { + @Override + public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, + RowPresenter.ViewHolder rowViewHolder, Row row) { + + Intent intent; + Bundle bundle; + if (((PhotoItem) item).getImageResourceId() == R.drawable.gallery_photo_6) { + GuidedStepSupportFragment.add(getFragmentManager(), + new GuidedStepSupportActivity.FirstStepFragment(), + android.R.id.content); + return; + } else if ( ((PhotoItem) item).getImageResourceId() == R.drawable.gallery_photo_8) { + intent = new Intent(getActivity(), BrowseSupportActivity.class); + bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity()) + .toBundle(); + } else if ( ((PhotoItem) item).getImageResourceId() == R.drawable.gallery_photo_7) { + intent = new Intent(getActivity(), RowsSupportActivity.class); + bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity()) + .toBundle(); + } else { + intent = new Intent(getActivity(), DetailsSupportActivity.class); + intent.putExtra(DetailsSupportActivity.EXTRA_ITEM, (PhotoItem) item); + bundle = ActivityOptionsCompat.makeSceneTransitionAnimation( + getActivity(), + ((ImageCardView)itemViewHolder.view).getMainImageView(), + DetailsSupportActivity.SHARED_ELEMENT_NAME).toBundle(); + } + getActivity().startActivity(intent, bundle); + } + } +} diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsActivity.java index f199e9d14..1ec104178 100644 --- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsActivity.java +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsActivity.java @@ -21,10 +21,9 @@ public class DetailsActivity extends Activity public static final String EXTRA_ITEM = "item"; public static final String SHARED_ELEMENT_NAME = "hero"; - public static boolean USE_LEGACY_PRESENTER = false; - private boolean useLegacyFragment() { - return (USE_LEGACY_PRESENTER && !(this instanceof SearchDetailsActivity)); + return (DetailsPresenterSelectionActivity.USE_LEGACY_PRESENTER + && !(this instanceof SearchDetailsActivity)); } /** Called when the activity is first created. */ diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsPresenterSelectionActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsPresenterSelectionActivity.java index ac0b67154..9fe7fd359 100644 --- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsPresenterSelectionActivity.java +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsPresenterSelectionActivity.java @@ -40,6 +40,7 @@ public class DetailsPresenterSelectionActivity extends Activity { private static final long ACTION_ID_SWITCH_LEGACY_ON = 10000; private static final long ACTION_ID_SWITCH_LEGACY_OFF = 10001; + public static boolean USE_LEGACY_PRESENTER = false; private static final String[] OPTION_NAMES = { "Use new details presenter", "Use legacy details presenter" }; private static final String[] OPTION_DESCRIPTIONS = { "Use new details presenter", @@ -49,7 +50,7 @@ public class DetailsPresenterSelectionActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - GuidedStepFragment.add(getFragmentManager(), new SetupFragment()); + GuidedStepFragment.addAsRoot(this, new SetupFragment(), android.R.id.content); } private static void addAction(List<GuidedAction> actions, long id, String title, String desc) { @@ -97,11 +98,11 @@ public class DetailsPresenterSelectionActivity extends Activity { for (int i = 0; i < OPTION_NAMES.length; i++) { boolean checked = false; if (OPTION_IDS[i] == ACTION_ID_SWITCH_LEGACY_ON) { - if (DetailsActivity.USE_LEGACY_PRESENTER) { + if (USE_LEGACY_PRESENTER) { checked = true; } } else if (OPTION_IDS[i] == ACTION_ID_SWITCH_LEGACY_OFF) { - if (!DetailsActivity.USE_LEGACY_PRESENTER) { + if (!USE_LEGACY_PRESENTER) { checked = true; } } @@ -113,9 +114,9 @@ public class DetailsPresenterSelectionActivity extends Activity { @Override public void onGuidedActionClicked(GuidedAction action) { if (action.getId() == ACTION_ID_SWITCH_LEGACY_ON) { - DetailsActivity.USE_LEGACY_PRESENTER = action.isChecked(); + USE_LEGACY_PRESENTER = action.isChecked(); } else if (action.getId() == ACTION_ID_SWITCH_LEGACY_OFF) { - DetailsActivity.USE_LEGACY_PRESENTER = !action.isChecked(); + USE_LEGACY_PRESENTER = !action.isChecked(); } getActivity().finish(); } diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsSupportActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsSupportActivity.java new file mode 100644 index 000000000..40c21097a --- /dev/null +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsSupportActivity.java @@ -0,0 +1,61 @@ +/* This file is auto-generated from DetailsActivity.java. DO NOT MODIFY. */ + +/* + * Copyright (C) 2014 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 com.example.android.leanback; + +import android.support.v4.app.FragmentActivity; +import android.os.Bundle; + +public class DetailsSupportActivity extends FragmentActivity +{ + public static final String EXTRA_ITEM = "item"; + public static final String SHARED_ELEMENT_NAME = "hero"; + + private boolean useLegacyFragment() { + return (DetailsPresenterSelectionActivity.USE_LEGACY_PRESENTER + && !(this instanceof SearchDetailsSupportActivity)); + } + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(useLegacyFragment() ? R.layout.legacy_details_support : R.layout.details_support); + if (savedInstanceState == null) { + // Only pass object to fragment when activity is first time created, + // later object is modified and persisted with fragment state. + if (useLegacyFragment()) { + ((DetailsSupportFragment)getSupportFragmentManager().findFragmentById(R.id.details_fragment)) + .setItem((PhotoItem) getIntent().getParcelableExtra(EXTRA_ITEM)); + } else { + ((NewDetailsSupportFragment)getSupportFragmentManager().findFragmentById(R.id.details_fragment)) + .setItem((PhotoItem) getIntent().getParcelableExtra(EXTRA_ITEM)); + } + } + } + + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + BackgroundHelper.attach(this); + } + + @Override + public void onStop() { + BackgroundHelper.release(this); + super.onStop(); + } +} diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsSupportFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsSupportFragment.java new file mode 100644 index 000000000..143a37d51 --- /dev/null +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/DetailsSupportFragment.java @@ -0,0 +1,218 @@ +/* This file is auto-generated from DetailsFragment.java. DO NOT MODIFY. */ + +/* + * Copyright (C) 2014 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 com.example.android.leanback; + +import android.content.Intent; +import android.content.res.Resources; +import android.os.Bundle; +import android.os.Handler; +import android.support.v4.app.ActivityOptionsCompat; +import android.support.v17.leanback.widget.Action; +import android.support.v17.leanback.widget.ArrayObjectAdapter; +import android.support.v17.leanback.widget.ClassPresenterSelector; +import android.support.v17.leanback.widget.DetailsOverviewRow; +import android.support.v17.leanback.widget.DetailsOverviewRowPresenter; +import android.support.v17.leanback.widget.HeaderItem; +import android.support.v17.leanback.widget.ImageCardView; +import android.support.v17.leanback.widget.ListRow; +import android.support.v17.leanback.widget.ListRowPresenter; +import android.support.v17.leanback.widget.OnActionClickedListener; +import android.support.v17.leanback.widget.OnItemViewClickedListener; +import android.support.v17.leanback.widget.OnItemViewSelectedListener; +import android.support.v17.leanback.widget.Presenter; +import android.support.v17.leanback.widget.Row; +import android.support.v17.leanback.widget.RowPresenter; +import android.support.v17.leanback.widget.SparseArrayObjectAdapter; +import android.util.Log; +import android.view.View; +import android.widget.Toast; + +public class DetailsSupportFragment extends android.support.v17.leanback.app.DetailsSupportFragment { + private static final String TAG = "leanback.DetailsSupportFragment"; + private static final String ITEM = "item"; + + private static final int NUM_ROWS = 3; + private ArrayObjectAdapter mRowsAdapter; + private PhotoItem mPhotoItem; + final CardPresenter cardPresenter = new CardPresenter(); + private BackgroundHelper mBackgroundHelper = new BackgroundHelper(); + + private static final int ACTION_PLAY = 1; + private static final int ACTION_RENT = 2; + private static final int ACTION_BUY = 3; + + private static final boolean TEST_SHARED_ELEMENT_TRANSITION = true; + private static final boolean TEST_ENTRANCE_TRANSITION = true; + + private static final long TIME_TO_LOAD_OVERVIEW_ROW_MS = 1000; + private static final long TIME_TO_LOAD_RELATED_ROWS_MS = 2000; + + private Action mActionPlay; + private Action mActionRent; + private Action mActionBuy; + + @Override + public void onCreate(Bundle savedInstanceState) { + Log.i(TAG, "onCreate"); + super.onCreate(savedInstanceState); + + setBadgeDrawable(getActivity().getResources().getDrawable(R.drawable.ic_title)); + setTitle("Leanback Sample App"); + setOnSearchClickedListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(getActivity(), SearchSupportActivity.class); + startActivity(intent); + } + }); + + mActionPlay = new Action(ACTION_PLAY, "Play"); + mActionRent = new Action(ACTION_RENT, "Rent", "$3.99", + getResources().getDrawable(R.drawable.ic_action_a)); + mActionBuy = new Action(ACTION_BUY, "Buy $9.99"); + + ClassPresenterSelector ps = new ClassPresenterSelector(); + DetailsOverviewRowPresenter dorPresenter = + new DetailsOverviewRowPresenter(new DetailsDescriptionPresenter()); + dorPresenter.setOnActionClickedListener(new OnActionClickedListener() { + @Override + public void onActionClicked(Action action) { + Toast.makeText(getActivity(), action.toString(), Toast.LENGTH_SHORT).show(); + DetailsOverviewRow dor = (DetailsOverviewRow) mRowsAdapter.get(0); + if (action.getId() == ACTION_BUY) { + // on the UI thread, we can modify actions adapter directly + SparseArrayObjectAdapter actions = (SparseArrayObjectAdapter) + dor.getActionsAdapter(); + actions.set(ACTION_PLAY, mActionPlay); + actions.clear(ACTION_RENT); + actions.clear(ACTION_BUY); + dor.setItem(mPhotoItem.getTitle() + "(Owned)"); + dor.setImageDrawable(getResources().getDrawable(R.drawable.details_img_16x9)); + } else if (action.getId() == ACTION_RENT) { + // on the UI thread, we can modify actions adapter directly + SparseArrayObjectAdapter actions = (SparseArrayObjectAdapter) + dor.getActionsAdapter(); + actions.set(ACTION_PLAY, mActionPlay); + actions.clear(ACTION_RENT); + dor.setItem(mPhotoItem.getTitle() + "(Rented)"); + } else if (action.getId() == ACTION_PLAY) { + Intent intent = new Intent(getActivity(), PlaybackOverlaySupportActivity.class); + getActivity().startActivity(intent); + } + } + }); + + ps.addClassPresenter(DetailsOverviewRow.class, dorPresenter); + ps.addClassPresenter(ListRow.class, new ListRowPresenter()); + + mRowsAdapter = new ArrayObjectAdapter(ps); + + PhotoItem item = (PhotoItem) (savedInstanceState != null ? + savedInstanceState.getParcelable(ITEM) : null); + if (item != null) { + setItem(item); + } + + setOnItemViewClickedListener(new OnItemViewClickedListener() { + @Override + public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, + RowPresenter.ViewHolder rowViewHolder, Row row) { + Log.i(TAG, "onItemClicked: " + item + " row " + row); + if (item instanceof PhotoItem){ + Intent intent = new Intent(getActivity(), DetailsSupportActivity.class); + intent.putExtra(DetailsSupportActivity.EXTRA_ITEM, (PhotoItem) item); + + Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation( + getActivity(), + ((ImageCardView)itemViewHolder.view).getMainImageView(), + DetailsSupportActivity.SHARED_ELEMENT_NAME).toBundle(); + getActivity().startActivity(intent, bundle); + } + } + }); + setOnItemViewSelectedListener(new OnItemViewSelectedListener() { + @Override + public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, + RowPresenter.ViewHolder rowViewHolder, Row row) { + Log.i(TAG, "onItemSelected: " + item + " row " + row); + } + }); + + if (TEST_SHARED_ELEMENT_TRANSITION) { + dorPresenter.setSharedElementEnterTransition(getActivity(), + DetailsSupportActivity.SHARED_ELEMENT_NAME); + } + if (TEST_ENTRANCE_TRANSITION) { + // don't run entrance transition if Activity is restored. + if (savedInstanceState == null) { + prepareEntranceTransition(); + } + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putParcelable(ITEM, mPhotoItem); + } + + public void setItem(PhotoItem photoItem) { + mPhotoItem = photoItem; + + mRowsAdapter.clear(); + new Handler().postDelayed(new Runnable() { + public void run() { + Resources res = getActivity().getResources(); + DetailsOverviewRow dor = new DetailsOverviewRow(mPhotoItem.getTitle()); + dor.setImageDrawable(res.getDrawable(mPhotoItem.getImageResourceId())); + SparseArrayObjectAdapter adapter = new SparseArrayObjectAdapter(); + adapter.set(ACTION_RENT, mActionRent); + adapter.set(ACTION_BUY, mActionBuy); + dor.setActionsAdapter(adapter); + mRowsAdapter.add(0, dor); + setSelectedPosition(0, false); + } + }, TIME_TO_LOAD_OVERVIEW_ROW_MS); + + new Handler().postDelayed(new Runnable() { + public void run() { + for (int i = 0; i < NUM_ROWS; ++i) { + ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter); + listRowAdapter.add(new PhotoItem("Hello world", R.drawable.gallery_photo_1)); + listRowAdapter.add(new PhotoItem("This is a test", R.drawable.gallery_photo_2)); + listRowAdapter.add(new PhotoItem("Android TV", R.drawable.gallery_photo_3)); + listRowAdapter.add(new PhotoItem("Leanback", R.drawable.gallery_photo_4)); + HeaderItem header = new HeaderItem(i, "Row " + i); + mRowsAdapter.add(new ListRow(header, listRowAdapter)); + } + if (TEST_ENTRANCE_TRANSITION) { + startEntranceTransition(); + } + } + }, TIME_TO_LOAD_RELATED_ROWS_MS); + setAdapter(mRowsAdapter); + } + + @Override + public void onStart() { + super.onStart(); + if (mPhotoItem != null) { + mBackgroundHelper.setBackground( + getActivity(), mPhotoItem.getImageResourceId()); + } + } + +} diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/ErrorSupportFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/ErrorSupportFragment.java new file mode 100644 index 000000000..ea3e17c2e --- /dev/null +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/ErrorSupportFragment.java @@ -0,0 +1,56 @@ +/* This file is auto-generated from ErrorFragment.java. DO NOT MODIFY. */ + +/* + * Copyright (C) 2014 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 com.example.android.leanback; + +import android.content.Intent; +import android.content.res.Resources; +import android.os.Bundle; +import android.support.v17.leanback.widget.ArrayObjectAdapter; +import android.support.v17.leanback.widget.HeaderItem; +import android.support.v17.leanback.widget.ListRow; +import android.support.v17.leanback.widget.ListRowPresenter; +import android.support.v17.leanback.widget.Row; +import android.support.v17.leanback.widget.SearchOrbView; +import android.util.Log; +import android.view.View; + +public class ErrorSupportFragment extends android.support.v17.leanback.app.ErrorSupportFragment { + private static final String TAG = "leanback.ErrorSupportFragment"; + private static final boolean TRANSLUCENT = true; + + @Override + public void onCreate(Bundle savedInstanceState) { + Log.i(TAG, "onCreate"); + super.onCreate(savedInstanceState); + + setTitle("Leanback Sample App"); + } + + void setErrorContent(Resources resources) { + setImageDrawable(resources.getDrawable(R.drawable.lb_ic_sad_cloud)); + setMessage("An error occurred."); + setDefaultBackground(TRANSLUCENT); + + setButtonText("Dismiss"); + setButtonClickListener(new View.OnClickListener() { + @Override + public void onClick(View arg0) { + Log.i(TAG, "button clicked"); + getFragmentManager().beginTransaction().remove(ErrorSupportFragment.this).commit(); + } + }); + } +} diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/GuidedStepActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/GuidedStepActivity.java index 1f9e96c8c..63149b444 100644 --- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/GuidedStepActivity.java +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/GuidedStepActivity.java @@ -20,15 +20,19 @@ import android.app.Activity; import android.app.FragmentManager; import android.content.Context; import android.content.Intent; +import android.content.res.Configuration; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.v17.leanback.app.GuidedStepFragment; import android.support.v17.leanback.widget.GuidedAction; import android.support.v17.leanback.widget.GuidanceStylist; import android.support.v17.leanback.widget.GuidanceStylist.Guidance; +import android.text.TextUtils; +import android.util.Log; +import android.view.ViewGroup; +import android.view.ViewTreeObserver.OnGlobalLayoutListener; import java.util.List; -import java.util.ArrayList; /** * Activity that showcases different aspects of GuidedStepFragments. @@ -38,6 +42,10 @@ public class GuidedStepActivity extends Activity { private static final int CONTINUE = 1; private static final int BACK = 2; + private static final int FIRST_NAME = 3; + private static final int LAST_NAME = 4; + private static final int PAYMENT = 5; + private static final int OPTION_CHECK_SET_ID = 10; private static final int DEFAULT_OPTION = 0; private static final String[] OPTION_NAMES = { "Option A", "Option B", "Option C" }; @@ -46,10 +54,31 @@ public class GuidedStepActivity extends Activity { private static final int[] OPTION_DRAWABLES = { R.drawable.ic_guidedstep_option_a, R.drawable.ic_guidedstep_option_b, R.drawable.ic_guidedstep_option_c }; + private static final String TAG = GuidedStepActivity.class.getSimpleName(); + @Override protected void onCreate(Bundle savedInstanceState) { + Log.v(TAG, "onCreate"); super.onCreate(savedInstanceState); - GuidedStepFragment.add(getFragmentManager(), new FirstStepFragment()); + GuidedStepFragment.addAsRoot(this, new FirstStepFragment(), android.R.id.content); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + Log.v(TAG, "onConfigurationChanged"); + super.onConfigurationChanged(newConfig); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + Log.v(TAG, "onSaveInstanceState"); + super.onSaveInstanceState(outState); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + Log.v(TAG, "onRestoreInstanceState"); + super.onRestoreInstanceState(savedInstanceState); } private static void addAction(List<GuidedAction> actions, long id, String title, String desc) { @@ -60,6 +89,26 @@ public class GuidedStepActivity extends Activity { .build()); } + private static void addEditableAction(List<GuidedAction> actions, long id, String title, String desc) { + actions.add(new GuidedAction.Builder() + .id(id) + .title(title) + .description(desc) + .editable(true) + .build()); + } + + private static void addEditableAction(List<GuidedAction> actions, long id, String title, + String editTitle, String desc) { + actions.add(new GuidedAction.Builder() + .id(id) + .title(title) + .editTitle(editTitle) + .description(desc) + .editable(true) + .build()); + } + private static void addCheckedAction(List<GuidedAction> actions, int iconResId, Context context, String title, String desc) { actions.add(new GuidedAction.Builder() @@ -70,9 +119,6 @@ public class GuidedStepActivity extends Activity { .build()); } - /** - * The first fragment is instantiated via XML, so it must be public. - */ public static class FirstStepFragment extends GuidedStepFragment { @Override public int onProvideTheme() { @@ -98,16 +144,19 @@ public class GuidedStepActivity extends Activity { public void onGuidedActionClicked(GuidedAction action) { FragmentManager fm = getFragmentManager(); if (action.getId() == CONTINUE) { - GuidedStepFragment.add(fm, new SecondStepFragment()); + GuidedStepFragment.add(fm, new SecondStepFragment(), android.R.id.content); } else { getActivity().finish(); } } - } - private static class SecondStepFragment extends GuidedStepFragment { + @Override + protected int getContainerIdForBackground() { + return R.id.lb_guidedstep_background; + } + } - private int mSelectedOption = DEFAULT_OPTION; + public static class SecondStepFragment extends GuidedStepFragment { @Override public Guidance onCreateGuidance(Bundle savedInstanceState) { @@ -119,6 +168,49 @@ public class GuidedStepActivity extends Activity { } @Override + public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) { + addEditableAction(actions, FIRST_NAME, "Pat", "Your first name"); + addEditableAction(actions, LAST_NAME, "Smith", "Your last name"); + addEditableAction(actions, PAYMENT, "Payment", "", "Input credit card number"); + addAction(actions, CONTINUE, "Continue", "Continue"); + } + + @Override + public void onGuidedActionClicked(GuidedAction action) { + if (action.getId() == CONTINUE) { + FragmentManager fm = getFragmentManager(); + GuidedStepFragment.add(fm, new ThirdStepFragment()); + } + } + + @Override + public void onGuidedActionEdited(GuidedAction action) { + CharSequence editTitle = action.getEditTitle(); + if (TextUtils.isDigitsOnly(editTitle) && editTitle.length() == 16) { + editTitle = editTitle.subSequence(editTitle.length() - 4, editTitle.length()); + action.setDescription("Visa XXXX-XXXX-XXXX-"+editTitle); + } else if (editTitle.length() == 0){ + action.setDescription("Input credit card number"); + } else { + action.setDescription("Error credit card number"); + } + } + } + + public static class ThirdStepFragment extends GuidedStepFragment { + + private int mSelectedOption = DEFAULT_OPTION; + + @Override + public Guidance onCreateGuidance(Bundle savedInstanceState) { + String title = getString(R.string.guidedstep_third_title); + String breadcrumb = getString(R.string.guidedstep_third_breadcrumb); + String description = getString(R.string.guidedstep_third_description); + Drawable icon = getActivity().getDrawable(R.drawable.ic_main_icon); + return new Guidance(title, description, breadcrumb, icon); + } + + @Override public GuidanceStylist onCreateGuidanceStylist() { return new GuidanceStylist() { @Override @@ -153,7 +245,11 @@ public class GuidedStepActivity extends Activity { public void onGuidedActionClicked(GuidedAction action) { if (action.getId() == CONTINUE) { FragmentManager fm = getFragmentManager(); - GuidedStepFragment.add(fm, new ThirdStepFragment(mSelectedOption)); + FourthStepFragment f = new FourthStepFragment(); + Bundle arguments = new Bundle(); + arguments.putInt(FourthStepFragment.EXTRA_OPTION, mSelectedOption); + f.setArguments(arguments); + GuidedStepFragment.add(fm, f, android.R.id.content); } else { mSelectedOption = getSelectedActionPosition()-1; } @@ -161,18 +257,23 @@ public class GuidedStepActivity extends Activity { } - private static class ThirdStepFragment extends GuidedStepFragment { - private final int mOption; + public static class FourthStepFragment extends GuidedStepFragment { + public static final String EXTRA_OPTION = "extra_option"; - public ThirdStepFragment(int option) { - mOption = option; + public FourthStepFragment() { + } + + public int getOption() { + Bundle b = getArguments(); + if (b == null) return 0; + return b.getInt(EXTRA_OPTION, 0); } @Override public Guidance onCreateGuidance(Bundle savedInstanceState) { - String title = getString(R.string.guidedstep_third_title); - String breadcrumb = getString(R.string.guidedstep_third_breadcrumb); - String description = "You chose: " + OPTION_NAMES[mOption]; + String title = getString(R.string.guidedstep_fourth_title); + String breadcrumb = getString(R.string.guidedstep_fourth_breadcrumb); + String description = "You chose: " + OPTION_NAMES[getOption()]; Drawable icon = getActivity().getDrawable(R.drawable.ic_main_icon); return new Guidance(title, description, breadcrumb, icon); } diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/GuidedStepSupportActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/GuidedStepSupportActivity.java new file mode 100644 index 000000000..432c6c0f0 --- /dev/null +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/GuidedStepSupportActivity.java @@ -0,0 +1,300 @@ +/* This file is auto-generated from GuidedStepActivity.java. DO NOT MODIFY. */ + +/* + * Copyright (C) 2014 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 com.example.android.leanback; + +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; +import android.content.Context; +import android.content.Intent; +import android.content.res.Configuration; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.support.v17.leanback.app.GuidedStepSupportFragment; +import android.support.v17.leanback.widget.GuidedAction; +import android.support.v17.leanback.widget.GuidanceStylist; +import android.support.v17.leanback.widget.GuidanceStylist.Guidance; +import android.text.TextUtils; +import android.util.Log; +import android.view.ViewGroup; +import android.view.ViewTreeObserver.OnGlobalLayoutListener; + +import java.util.List; + +/** + * Activity that showcases different aspects of GuidedStepSupportFragments. + */ +public class GuidedStepSupportActivity extends FragmentActivity { + + private static final int CONTINUE = 1; + private static final int BACK = 2; + + private static final int FIRST_NAME = 3; + private static final int LAST_NAME = 4; + private static final int PAYMENT = 5; + + private static final int OPTION_CHECK_SET_ID = 10; + private static final int DEFAULT_OPTION = 0; + private static final String[] OPTION_NAMES = { "Option A", "Option B", "Option C" }; + private static final String[] OPTION_DESCRIPTIONS = { "Here's one thing you can do", + "Here's another thing you can do", "Here's one more thing you can do" }; + private static final int[] OPTION_DRAWABLES = { R.drawable.ic_guidedstep_option_a, + R.drawable.ic_guidedstep_option_b, R.drawable.ic_guidedstep_option_c }; + + private static final String TAG = GuidedStepSupportActivity.class.getSimpleName(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + Log.v(TAG, "onCreate"); + super.onCreate(savedInstanceState); + GuidedStepSupportFragment.addAsRoot(this, new FirstStepFragment(), android.R.id.content); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + Log.v(TAG, "onConfigurationChanged"); + super.onConfigurationChanged(newConfig); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + Log.v(TAG, "onSaveInstanceState"); + super.onSaveInstanceState(outState); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + Log.v(TAG, "onRestoreInstanceState"); + super.onRestoreInstanceState(savedInstanceState); + } + + private static void addAction(List<GuidedAction> actions, long id, String title, String desc) { + actions.add(new GuidedAction.Builder() + .id(id) + .title(title) + .description(desc) + .build()); + } + + private static void addEditableAction(List<GuidedAction> actions, long id, String title, String desc) { + actions.add(new GuidedAction.Builder() + .id(id) + .title(title) + .description(desc) + .editable(true) + .build()); + } + + private static void addEditableAction(List<GuidedAction> actions, long id, String title, + String editTitle, String desc) { + actions.add(new GuidedAction.Builder() + .id(id) + .title(title) + .editTitle(editTitle) + .description(desc) + .editable(true) + .build()); + } + + private static void addCheckedAction(List<GuidedAction> actions, int iconResId, Context context, + String title, String desc) { + actions.add(new GuidedAction.Builder() + .title(title) + .description(desc) + .checkSetId(OPTION_CHECK_SET_ID) + .iconResourceId(iconResId, context) + .build()); + } + + public static class FirstStepFragment extends GuidedStepSupportFragment { + @Override + public int onProvideTheme() { + return R.style.Theme_Example_Leanback_GuidedStep_First; + } + + @Override + public Guidance onCreateGuidance(Bundle savedInstanceState) { + String title = getString(R.string.guidedstep_first_title); + String breadcrumb = getString(R.string.guidedstep_first_breadcrumb); + String description = getString(R.string.guidedstep_first_description); + Drawable icon = getActivity().getDrawable(R.drawable.ic_main_icon); + return new Guidance(title, description, breadcrumb, icon); + } + + @Override + public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) { + addAction(actions, CONTINUE, "Continue", "Let's do it"); + addAction(actions, BACK, "Cancel", "Nevermind"); + } + + @Override + public void onGuidedActionClicked(GuidedAction action) { + FragmentManager fm = getFragmentManager(); + if (action.getId() == CONTINUE) { + GuidedStepSupportFragment.add(fm, new SecondStepFragment(), android.R.id.content); + } else { + getActivity().finish(); + } + } + + @Override + protected int getContainerIdForBackground() { + return R.id.lb_guidedstep_background; + } + } + + public static class SecondStepFragment extends GuidedStepSupportFragment { + + @Override + public Guidance onCreateGuidance(Bundle savedInstanceState) { + String title = getString(R.string.guidedstep_second_title); + String breadcrumb = getString(R.string.guidedstep_second_breadcrumb); + String description = getString(R.string.guidedstep_second_description); + Drawable icon = getActivity().getDrawable(R.drawable.ic_main_icon); + return new Guidance(title, description, breadcrumb, icon); + } + + @Override + public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) { + addEditableAction(actions, FIRST_NAME, "Pat", "Your first name"); + addEditableAction(actions, LAST_NAME, "Smith", "Your last name"); + addEditableAction(actions, PAYMENT, "Payment", "", "Input credit card number"); + addAction(actions, CONTINUE, "Continue", "Continue"); + } + + @Override + public void onGuidedActionClicked(GuidedAction action) { + if (action.getId() == CONTINUE) { + FragmentManager fm = getFragmentManager(); + GuidedStepSupportFragment.add(fm, new ThirdStepFragment()); + } + } + + @Override + public void onGuidedActionEdited(GuidedAction action) { + CharSequence editTitle = action.getEditTitle(); + if (TextUtils.isDigitsOnly(editTitle) && editTitle.length() == 16) { + editTitle = editTitle.subSequence(editTitle.length() - 4, editTitle.length()); + action.setDescription("Visa XXXX-XXXX-XXXX-"+editTitle); + } else if (editTitle.length() == 0){ + action.setDescription("Input credit card number"); + } else { + action.setDescription("Error credit card number"); + } + } + } + + public static class ThirdStepFragment extends GuidedStepSupportFragment { + + private int mSelectedOption = DEFAULT_OPTION; + + @Override + public Guidance onCreateGuidance(Bundle savedInstanceState) { + String title = getString(R.string.guidedstep_third_title); + String breadcrumb = getString(R.string.guidedstep_third_breadcrumb); + String description = getString(R.string.guidedstep_third_description); + Drawable icon = getActivity().getDrawable(R.drawable.ic_main_icon); + return new Guidance(title, description, breadcrumb, icon); + } + + @Override + public GuidanceStylist onCreateGuidanceStylist() { + return new GuidanceStylist() { + @Override + public int onProvideLayoutId() { + return R.layout.guidedstep_second_guidance; + } + }; + } + + @Override + public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) { + String desc = "The description can be quite long as well. "; + desc += "Just be sure to set multilineDescription to true in the GuidedAction."; + actions.add(new GuidedAction.Builder() + .title("Note that Guided Actions can have titles that are quite long.") + .description(desc) + .multilineDescription(true) + .infoOnly(true) + .enabled(false) + .build()); + for (int i = 0; i < OPTION_NAMES.length; i++) { + addCheckedAction(actions, OPTION_DRAWABLES[i], getActivity(), OPTION_NAMES[i], + OPTION_DESCRIPTIONS[i]); + if (i == DEFAULT_OPTION) { + actions.get(actions.size() -1).setChecked(true); + } + } + addAction(actions, CONTINUE, "Continue", ""); + } + + @Override + public void onGuidedActionClicked(GuidedAction action) { + if (action.getId() == CONTINUE) { + FragmentManager fm = getFragmentManager(); + FourthStepFragment f = new FourthStepFragment(); + Bundle arguments = new Bundle(); + arguments.putInt(FourthStepFragment.EXTRA_OPTION, mSelectedOption); + f.setArguments(arguments); + GuidedStepSupportFragment.add(fm, f, android.R.id.content); + } else { + mSelectedOption = getSelectedActionPosition()-1; + } + } + + } + + public static class FourthStepFragment extends GuidedStepSupportFragment { + public static final String EXTRA_OPTION = "extra_option"; + + public FourthStepFragment() { + } + + public int getOption() { + Bundle b = getArguments(); + if (b == null) return 0; + return b.getInt(EXTRA_OPTION, 0); + } + + @Override + public Guidance onCreateGuidance(Bundle savedInstanceState) { + String title = getString(R.string.guidedstep_fourth_title); + String breadcrumb = getString(R.string.guidedstep_fourth_breadcrumb); + String description = "You chose: " + OPTION_NAMES[getOption()]; + Drawable icon = getActivity().getDrawable(R.drawable.ic_main_icon); + return new Guidance(title, description, breadcrumb, icon); + } + + @Override + public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) { + addAction(actions, CONTINUE, "Done", "All finished"); + addAction(actions, BACK, "Back", "Forgot something..."); + } + + @Override + public void onGuidedActionClicked(GuidedAction action) { + if (action.getId() == CONTINUE) { + getActivity().finish(); + } else { + getFragmentManager().popBackStack(); + } + } + + } + +} diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/MainActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/MainActivity.java index c1b60f41c..711031664 100644 --- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/MainActivity.java +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/MainActivity.java @@ -20,6 +20,7 @@ import android.app.Activity; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.support.v4.app.ActivityOptionsCompat; import android.support.v17.leanback.app.GuidedStepFragment; import android.support.v17.leanback.widget.GuidedAction; import android.support.v17.leanback.widget.GuidanceStylist.Guidance; @@ -39,7 +40,8 @@ public class MainActivity extends Activity { super.onCreate(savedInstanceState); mGuidedStepFragment = new StepFragment(); - GuidedStepFragment.add(getFragmentManager(), mGuidedStepFragment); + GuidedStepFragment.addAsRoot(this, mGuidedStepFragment, android.R.id.content); + } public static class StepFragment extends GuidedStepFragment { @@ -55,24 +57,42 @@ public class MainActivity extends Activity { @Override public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) { addAction(actions, BrowseActivity.class, R.string.browse, R.string.browse_description); + addAction(actions, BrowseSupportActivity.class, R.string.browse_support, + R.string.browse_support_description); addAction(actions, SearchActivity.class, R.string.search, R.string.search_description); + addAction(actions, SearchSupportActivity.class, R.string.search_support, R.string.search_support_description); addAction(actions, DetailsActivity.class, R.string.details, R.string.details_description); actions.get(actions.size()-1).getIntent().putExtra(DetailsActivity.EXTRA_ITEM, new PhotoItem("Hello world", R.drawable.gallery_photo_1)); + addAction(actions, DetailsSupportActivity.class, R.string.details_support, R.string.details_support_description); + actions.get(actions.size()-1).getIntent().putExtra(DetailsSupportActivity.EXTRA_ITEM, + new PhotoItem("Hello world", R.drawable.gallery_photo_1)); addAction(actions, SearchDetailsActivity.class, R.string.search_details, R.string.search_details_description); - actions.get(actions.size()-1).getIntent().putExtra(DetailsActivity.EXTRA_ITEM, + actions.get(actions.size()-1).getIntent().putExtra(SearchDetailsActivity.EXTRA_ITEM, + new PhotoItem("Hello world", R.drawable.gallery_photo_1)); + addAction(actions, SearchDetailsSupportActivity.class, R.string.search_details_support, + R.string.search_details_support_description); + actions.get(actions.size()-1).getIntent().putExtra(SearchDetailsSupportActivity.EXTRA_ITEM, new PhotoItem("Hello world", R.drawable.gallery_photo_1)); - addAction(actions, PlaybackOverlayActivity.class, R.string.playback, - R.string.playback_description); - addAction(actions, HorizontalGridTestActivity.class, R.string.hgrid, - R.string.hgrid_description); addAction(actions, VerticalGridActivity.class, R.string.vgrid, R.string.vgrid_description); + addAction(actions, VerticalGridSupportActivity.class, R.string.vgrid_support, + R.string.vgrid_support_description); addAction(actions, GuidedStepActivity.class, R.string.guidedstep, R.string.guidedstep_description); + addAction(actions, GuidedStepSupportActivity.class, R.string.guidedstepsupport, + R.string.guidedstepsupport_description); addAction(actions, BrowseErrorActivity.class, R.string.browseerror, R.string.browseerror_description); + addAction(actions, BrowseErrorSupportActivity.class, R.string.browseerror_support, + R.string.browseerror_support_description); + addAction(actions, PlaybackOverlayActivity.class, R.string.playback, + R.string.playback_description); + addAction(actions, PlaybackOverlaySupportActivity.class, R.string.playback_support, + R.string.playback_support_description); + addAction(actions, HorizontalGridTestActivity.class, R.string.hgrid, + R.string.hgrid_description); addAction(actions, DetailsPresenterSelectionActivity.class, R.string.detail_presenter_options, R.string.detail_presenter_options_description); @@ -90,7 +110,9 @@ public class MainActivity extends Activity { public void onGuidedActionClicked(GuidedAction action) { Intent intent = action.getIntent(); if (intent != null) { - startActivity(intent); + Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity()) + .toBundle(); + startActivity(intent, bundle); } } diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/NewDetailsFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/NewDetailsFragment.java index 445e1486e..4d04502b5 100644 --- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/NewDetailsFragment.java +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/NewDetailsFragment.java @@ -68,8 +68,7 @@ public class NewDetailsFragment extends android.support.v17.leanback.app.Details private FullWidthDetailsOverviewSharedElementHelper mHelper; private void initializeTest() { - Activity activity = getActivity(); - TEST_SHARED_ELEMENT_TRANSITION = null != activity.getWindow().getSharedElementEnterTransition(); + TEST_SHARED_ELEMENT_TRANSITION = null != getActivity().getWindow().getSharedElementEnterTransition(); TEST_OVERVIEW_ROW_ON_SECOND = !TEST_SHARED_ELEMENT_TRANSITION; TEST_ENTRANCE_TRANSITION = true; } diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/NewDetailsSupportFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/NewDetailsSupportFragment.java new file mode 100644 index 000000000..8a43d8b79 --- /dev/null +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/NewDetailsSupportFragment.java @@ -0,0 +1,255 @@ +/* This file is auto-generated from NewDetailsFragment.java. DO NOT MODIFY. */ + +/* + * Copyright (C) 2014 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 com.example.android.leanback; + +import android.support.v4.app.FragmentActivity; +import android.content.Intent; +import android.content.res.Resources; +import android.os.Bundle; +import android.os.Handler; +import android.support.v4.app.ActivityOptionsCompat; +import android.support.v17.leanback.widget.Action; +import android.support.v17.leanback.widget.ArrayObjectAdapter; +import android.support.v17.leanback.widget.ClassPresenterSelector; +import android.support.v17.leanback.widget.DetailsOverviewRow; +import android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter; +import android.support.v17.leanback.widget.FullWidthDetailsOverviewSharedElementHelper; +import android.support.v17.leanback.widget.HeaderItem; +import android.support.v17.leanback.widget.ImageCardView; +import android.support.v17.leanback.widget.ListRow; +import android.support.v17.leanback.widget.ListRowPresenter; +import android.support.v17.leanback.widget.OnActionClickedListener; +import android.support.v17.leanback.widget.OnItemViewClickedListener; +import android.support.v17.leanback.widget.OnItemViewSelectedListener; +import android.support.v17.leanback.widget.Presenter; +import android.support.v17.leanback.widget.Row; +import android.support.v17.leanback.widget.RowPresenter; +import android.support.v17.leanback.widget.SparseArrayObjectAdapter; +import android.util.Log; +import android.view.View; +import android.widget.Toast; + +public class NewDetailsSupportFragment extends android.support.v17.leanback.app.DetailsSupportFragment { + private static final String TAG = "leanback.DetailsSupportFragment"; + private static final String ITEM = "item"; + + private static final int NUM_ROWS = 3; + private ArrayObjectAdapter mRowsAdapter; + private PhotoItem mPhotoItem; + final CardPresenter cardPresenter = new CardPresenter(); + private BackgroundHelper mBackgroundHelper = new BackgroundHelper(); + + private static final int ACTION_PLAY = 1; + private static final int ACTION_RENT = 2; + private static final int ACTION_BUY = 3; + + private boolean TEST_OVERVIEW_ROW_ON_SECOND; + private boolean TEST_SHARED_ELEMENT_TRANSITION; + private boolean TEST_ENTRANCE_TRANSITION; + + private static final long TIME_TO_LOAD_OVERVIEW_ROW_MS = 1000; + private static final long TIME_TO_LOAD_RELATED_ROWS_MS = 2000; + + private Action mActionPlay; + private Action mActionRent; + private Action mActionBuy; + + private FullWidthDetailsOverviewSharedElementHelper mHelper; + + private void initializeTest() { + TEST_SHARED_ELEMENT_TRANSITION = null != getActivity().getWindow().getSharedElementEnterTransition(); + TEST_OVERVIEW_ROW_ON_SECOND = !TEST_SHARED_ELEMENT_TRANSITION; + TEST_ENTRANCE_TRANSITION = true; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + Log.i(TAG, "onCreate"); + super.onCreate(savedInstanceState); + initializeTest(); + + setBadgeDrawable(getActivity().getResources().getDrawable(R.drawable.ic_title)); + setTitle("Leanback Sample App"); + setOnSearchClickedListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(getActivity(), SearchSupportActivity.class); + startActivity(intent); + } + }); + + mActionPlay = new Action(ACTION_PLAY, "Play"); + mActionRent = new Action(ACTION_RENT, "Rent", "$3.99", + getResources().getDrawable(R.drawable.ic_action_a)); + mActionBuy = new Action(ACTION_BUY, "Buy $9.99"); + + ClassPresenterSelector ps = new ClassPresenterSelector(); + FullWidthDetailsOverviewRowPresenter dorPresenter = + new FullWidthDetailsOverviewRowPresenter(new DetailsDescriptionPresenter()); + dorPresenter.setOnActionClickedListener(new OnActionClickedListener() { + @Override + public void onActionClicked(Action action) { + Toast.makeText(getActivity(), action.toString(), Toast.LENGTH_SHORT).show(); + int indexOfOverviewRow = TEST_OVERVIEW_ROW_ON_SECOND ? 1 : 0; + DetailsOverviewRow dor = (DetailsOverviewRow) mRowsAdapter.get(indexOfOverviewRow); + if (action.getId() == ACTION_BUY) { + // on the UI thread, we can modify actions adapter directly + SparseArrayObjectAdapter actions = (SparseArrayObjectAdapter) + dor.getActionsAdapter(); + actions.set(ACTION_PLAY, mActionPlay); + actions.clear(ACTION_RENT); + actions.clear(ACTION_BUY); + dor.setItem(mPhotoItem.getTitle() + "(Owned)"); + dor.setImageDrawable(getResources().getDrawable(R.drawable.details_img_16x9)); + } else if (action.getId() == ACTION_RENT) { + // on the UI thread, we can modify actions adapter directly + SparseArrayObjectAdapter actions = (SparseArrayObjectAdapter) + dor.getActionsAdapter(); + actions.set(ACTION_PLAY, mActionPlay); + actions.clear(ACTION_RENT); + dor.setItem(mPhotoItem.getTitle() + "(Rented)"); + } else if (action.getId() == ACTION_PLAY) { + Intent intent = new Intent(getActivity(), PlaybackOverlaySupportActivity.class); + getActivity().startActivity(intent); + } + } + }); + if (TEST_OVERVIEW_ROW_ON_SECOND) { + dorPresenter.setInitialState(FullWidthDetailsOverviewRowPresenter.STATE_SMALL); + } + + ps.addClassPresenter(DetailsOverviewRow.class, dorPresenter); + ps.addClassPresenter(ListRow.class, new ListRowPresenter()); + + mRowsAdapter = new ArrayObjectAdapter(ps); + + PhotoItem item = (PhotoItem) (savedInstanceState != null ? + savedInstanceState.getParcelable(ITEM) : null); + if (item != null) { + setItem(item); + } + + setOnItemViewClickedListener(new OnItemViewClickedListener() { + @Override + public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, + RowPresenter.ViewHolder rowViewHolder, Row row) { + Log.i(TAG, "onItemClicked: " + item + " row " + row); + if (item instanceof PhotoItem){ + Intent intent = new Intent(getActivity(), DetailsSupportActivity.class); + intent.putExtra(DetailsSupportActivity.EXTRA_ITEM, (PhotoItem) item); + + Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation( + getActivity(), + ((ImageCardView)itemViewHolder.view).getMainImageView(), + DetailsSupportActivity.SHARED_ELEMENT_NAME).toBundle(); + getActivity().startActivity(intent, bundle); + } + } + }); + setOnItemViewSelectedListener(new OnItemViewSelectedListener() { + @Override + public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, + RowPresenter.ViewHolder rowViewHolder, Row row) { + Log.i(TAG, "onItemSelected: " + item + " row " + row); + } + }); + + if (TEST_SHARED_ELEMENT_TRANSITION) { + mHelper = new FullWidthDetailsOverviewSharedElementHelper(); + mHelper.setSharedElementEnterTransition(getActivity(), + DetailsSupportActivity.SHARED_ELEMENT_NAME); + dorPresenter.setListener(mHelper); + dorPresenter.setParticipatingEntranceTransition(false); + } else { + dorPresenter.setParticipatingEntranceTransition(true); + } + if (TEST_ENTRANCE_TRANSITION) { + // don't run entrance transition if Activity is restored. + if (savedInstanceState == null) { + prepareEntranceTransition(); + } + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putParcelable(ITEM, mPhotoItem); + } + + public void setItem(PhotoItem photoItem) { + mPhotoItem = photoItem; + + mRowsAdapter.clear(); + new Handler().postDelayed(new Runnable() { + public void run() { + if (TEST_OVERVIEW_ROW_ON_SECOND) { + ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter); + listRowAdapter.add(new PhotoItem("Hello world", R.drawable.gallery_photo_1)); + listRowAdapter.add(new PhotoItem("This is a test", R.drawable.gallery_photo_2)); + listRowAdapter.add(new PhotoItem("Android TV", R.drawable.gallery_photo_3)); + listRowAdapter.add(new PhotoItem("Leanback", R.drawable.gallery_photo_4)); + HeaderItem header = new HeaderItem(0, "Search Result"); + mRowsAdapter.add(0, new ListRow(header, listRowAdapter)); + } + + Resources res = getActivity().getResources(); + DetailsOverviewRow dor = new DetailsOverviewRow(mPhotoItem.getTitle()); + dor.setImageDrawable(res.getDrawable(mPhotoItem.getImageResourceId())); + SparseArrayObjectAdapter adapter = new SparseArrayObjectAdapter(); + adapter.set(ACTION_RENT, mActionRent); + adapter.set(ACTION_BUY, mActionBuy); + dor.setActionsAdapter(adapter); + int indexOfOverviewRow = TEST_OVERVIEW_ROW_ON_SECOND ? 1 : 0; + mRowsAdapter.add(indexOfOverviewRow, dor); + setSelectedPosition(0, true); + if (TEST_SHARED_ELEMENT_TRANSITION) { + if (mHelper != null && !mHelper.getAutoStartSharedElementTransition()) { + mHelper.startPostponedEnterTransition(); + } + } + } + }, TIME_TO_LOAD_OVERVIEW_ROW_MS); + + new Handler().postDelayed(new Runnable() { + public void run() { + for (int i = 0; i < NUM_ROWS; ++i) { + ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter); + listRowAdapter.add(new PhotoItem("Hello world", R.drawable.gallery_photo_1)); + listRowAdapter.add(new PhotoItem("This is a test", R.drawable.gallery_photo_2)); + listRowAdapter.add(new PhotoItem("Android TV", R.drawable.gallery_photo_3)); + listRowAdapter.add(new PhotoItem("Leanback", R.drawable.gallery_photo_4)); + HeaderItem header = new HeaderItem(i, "Row " + i); + mRowsAdapter.add(new ListRow(header, listRowAdapter)); + } + if (TEST_ENTRANCE_TRANSITION) { + startEntranceTransition(); + } + } + }, TIME_TO_LOAD_RELATED_ROWS_MS); + setAdapter(mRowsAdapter); + } + + @Override + public void onStart() { + super.onStart(); + if (mPhotoItem != null) { + mBackgroundHelper.setBackground( + getActivity(), mPhotoItem.getImageResourceId()); + } + } + +} diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackControlSupportHelper.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackControlSupportHelper.java new file mode 100644 index 000000000..b857e17c7 --- /dev/null +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackControlSupportHelper.java @@ -0,0 +1,280 @@ +/* This file is auto-generated from PlaybackControlHelper.java. DO NOT MODIFY. */ + +/* + * 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 com.example.android.leanback; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.support.v17.leanback.app.PlaybackControlSupportGlue; +import android.support.v17.leanback.widget.Action; +import android.support.v17.leanback.widget.ArrayObjectAdapter; +import android.support.v17.leanback.widget.ControlButtonPresenterSelector; +import android.support.v17.leanback.widget.PlaybackControlsRow; +import android.support.v17.leanback.widget.PlaybackControlsRowPresenter; +import android.support.v17.leanback.widget.PresenterSelector; +import android.support.v17.leanback.widget.SparseArrayObjectAdapter; +import android.view.KeyEvent; +import android.view.View; +import android.widget.Toast; + +abstract class PlaybackControlSupportHelper extends PlaybackControlSupportGlue { + /** + * Change the location of the thumbs up/down controls + */ + private static final boolean THUMBS_PRIMARY = true; + + private static final String FAUX_TITLE = "A short song of silence"; + private static final String FAUX_SUBTITLE = "2014"; + private static final int FAUX_DURATION = 33 * 1000; + + // These should match the playback service FF behavior + private static int[] sFastForwardSpeeds = { 2, 3, 4, 5 }; + + private boolean mIsPlaying; + private int mSpeed = PlaybackControlSupportGlue.PLAYBACK_SPEED_PAUSED; + private long mStartTime; + private long mStartPosition = 0; + + private PlaybackControlsRow.RepeatAction mRepeatAction; + private PlaybackControlsRow.ThumbsUpAction mThumbsUpAction; + private PlaybackControlsRow.ThumbsDownAction mThumbsDownAction; + + private Handler mHandler = new Handler(); + private final Runnable mUpdateProgressRunnable = new Runnable() { + @Override + public void run() { + updateProgress(); + mHandler.postDelayed(this, getUpdatePeriod()); + } + }; + + public PlaybackControlSupportHelper(Context context, PlaybackOverlaySupportFragment fragment) { + super(context, fragment, sFastForwardSpeeds); + mThumbsUpAction = new PlaybackControlsRow.ThumbsUpAction(context); + mThumbsUpAction.setIndex(PlaybackControlsRow.ThumbsUpAction.OUTLINE); + mThumbsDownAction = new PlaybackControlsRow.ThumbsDownAction(context); + mThumbsDownAction.setIndex(PlaybackControlsRow.ThumbsDownAction.OUTLINE); + mRepeatAction = new PlaybackControlsRow.RepeatAction(context); + } + + @Override + public PlaybackControlsRowPresenter createControlsRowAndPresenter() { + PlaybackControlsRowPresenter presenter = super.createControlsRowAndPresenter(); + + ArrayObjectAdapter adapter = new ArrayObjectAdapter(new ControlButtonPresenterSelector()); + getControlsRow().setSecondaryActionsAdapter(adapter); + if (!THUMBS_PRIMARY) { + adapter.add(mThumbsDownAction); + } + adapter.add(mRepeatAction); + if (!THUMBS_PRIMARY) { + adapter.add(mThumbsUpAction); + } + + return presenter; + } + + @Override + protected SparseArrayObjectAdapter createPrimaryActionsAdapter( + PresenterSelector presenterSelector) { + SparseArrayObjectAdapter adapter = new SparseArrayObjectAdapter(presenterSelector); + if (THUMBS_PRIMARY) { + adapter.set(PlaybackControlSupportGlue.ACTION_CUSTOM_LEFT_FIRST, mThumbsUpAction); + adapter.set(PlaybackControlSupportGlue.ACTION_CUSTOM_RIGHT_FIRST, mThumbsDownAction); + } + return adapter; + } + + @Override + public void onActionClicked(Action action) { + if (shouldDispatchAction(action)) { + dispatchAction(action); + return; + } + super.onActionClicked(action); + } + + @Override + public boolean onKey(View view, int keyCode, KeyEvent keyEvent) { + if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) { + Action action = getControlsRow().getActionForKeyCode(keyEvent.getKeyCode()); + if (shouldDispatchAction(action)) { + dispatchAction(action); + return true; + } + } + return super.onKey(view, keyCode, keyEvent); + } + + private boolean shouldDispatchAction(Action action) { + return action == mRepeatAction || action == mThumbsUpAction || action == mThumbsDownAction; + } + + private void dispatchAction(Action action) { + Toast.makeText(getContext(), action.toString(), Toast.LENGTH_SHORT).show(); + PlaybackControlsRow.MultiAction multiAction = (PlaybackControlsRow.MultiAction) action; + multiAction.nextIndex(); + notifyActionChanged(multiAction); + } + + private void notifyActionChanged(PlaybackControlsRow.MultiAction action) { + int index; + index = getPrimaryActionsAdapter().indexOf(action); + if (index >= 0) { + getPrimaryActionsAdapter().notifyArrayItemRangeChanged(index, 1); + } else { + index = getSecondaryActionsAdapter().indexOf(action); + if (index >= 0) { + getSecondaryActionsAdapter().notifyArrayItemRangeChanged(index, 1); + } + } + } + + private SparseArrayObjectAdapter getPrimaryActionsAdapter() { + return (SparseArrayObjectAdapter) getControlsRow().getPrimaryActionsAdapter(); + } + + private ArrayObjectAdapter getSecondaryActionsAdapter() { + return (ArrayObjectAdapter) getControlsRow().getSecondaryActionsAdapter(); + } + + @Override + public boolean hasValidMedia() { + return true; + } + + @Override + public boolean isMediaPlaying() { + return mIsPlaying; + } + + @Override + public CharSequence getMediaTitle() { + return FAUX_TITLE; + } + + @Override + public CharSequence getMediaSubtitle() { + return FAUX_SUBTITLE; + } + + @Override + public int getMediaDuration() { + return FAUX_DURATION; + } + + @Override + public Drawable getMediaArt() { + return null; + } + + @Override + public long getSupportedActions() { + return PlaybackControlSupportGlue.ACTION_PLAY_PAUSE | + PlaybackControlSupportGlue.ACTION_FAST_FORWARD | + PlaybackControlSupportGlue.ACTION_REWIND; + } + + @Override + public int getCurrentSpeedId() { + return mSpeed; + } + + @Override + public int getCurrentPosition() { + int speed; + if (mSpeed == PlaybackControlSupportGlue.PLAYBACK_SPEED_PAUSED) { + speed = 0; + } else if (mSpeed == PlaybackControlSupportGlue.PLAYBACK_SPEED_NORMAL) { + speed = 1; + } else if (mSpeed >= PlaybackControlSupportGlue.PLAYBACK_SPEED_FAST_L0) { + int index = mSpeed - PlaybackControlSupportGlue.PLAYBACK_SPEED_FAST_L0; + speed = getFastForwardSpeeds()[index]; + } else if (mSpeed <= -PlaybackControlSupportGlue.PLAYBACK_SPEED_FAST_L0) { + int index = -mSpeed - PlaybackControlSupportGlue.PLAYBACK_SPEED_FAST_L0; + speed = -getRewindSpeeds()[index]; + } else { + return -1; + } + long position = mStartPosition + + (System.currentTimeMillis() - mStartTime) * speed; + if (position > getMediaDuration()) { + position = getMediaDuration(); + onPlaybackComplete(true); + } else if (position < 0) { + position = 0; + onPlaybackComplete(false); + } + return (int) position; + } + + void onPlaybackComplete(final boolean ended) { + mHandler.post(new Runnable() { + @Override + public void run() { + if (mRepeatAction.getIndex() == PlaybackControlsRow.RepeatAction.NONE) { + pausePlayback(); + } else { + startPlayback(PlaybackControlSupportGlue.PLAYBACK_SPEED_NORMAL); + } + mStartPosition = 0; + onStateChanged(); + } + }); + } + + @Override + protected void startPlayback(int speed) { + if (speed == mSpeed) { + return; + } + mStartPosition = getCurrentPosition(); + mSpeed = speed; + mIsPlaying = true; + mStartTime = System.currentTimeMillis(); + } + + @Override + protected void pausePlayback() { + if (mSpeed == PlaybackControlSupportGlue.PLAYBACK_SPEED_PAUSED) { + return; + } + mStartPosition = getCurrentPosition(); + mSpeed = PlaybackControlSupportGlue.PLAYBACK_SPEED_PAUSED; + mIsPlaying = false; + } + + @Override + protected void skipToNext() { + // Not supported + } + + @Override + protected void skipToPrevious() { + // Not supported + } + + @Override + public void enableProgressUpdating(boolean enable) { + mHandler.removeCallbacks(mUpdateProgressRunnable); + if (enable) { + mUpdateProgressRunnable.run(); + } + } +};
\ No newline at end of file diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlayFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlayFragment.java index 0cb981ad8..6658c67f7 100644 --- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlayFragment.java +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlayFragment.java @@ -37,6 +37,9 @@ import android.support.v17.leanback.widget.OnItemViewClickedListener; import android.support.v17.leanback.widget.ControlButtonPresenterSelector; import android.support.v17.leanback.widget.SparseArrayObjectAdapter; import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; import android.widget.Toast; public class PlaybackOverlayFragment extends android.support.v17.leanback.app.PlaybackOverlayFragment { @@ -102,7 +105,7 @@ public class PlaybackOverlayFragment extends android.support.v17.leanback.app.Pl @Override public int getUpdatePeriod() { int totalTime = getControlsRow().getTotalTime(); - if (getView() == null || totalTime <= 0) { + if (getView() == null || getView().getWidth() == 0 || totalTime <= 0) { return 1000; } return Math.max(16, totalTime / getView().getWidth()); @@ -149,11 +152,13 @@ public class PlaybackOverlayFragment extends android.support.v17.leanback.app.Pl HeaderItem header = new HeaderItem(i, "Row " + i); getAdapter().set(ROW_CONTROLS + 1 + i, new ListRow(header, listRowAdapter)); } + } @Override public void onStart() { super.onStart(); + mGlue.setFadingEnabled(true); mGlue.enableProgressUpdating(mGlue.hasValidMedia() && mGlue.isMediaPlaying()); } diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlaySupportActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlaySupportActivity.java new file mode 100644 index 000000000..a2f5e5a00 --- /dev/null +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlaySupportActivity.java @@ -0,0 +1,30 @@ +/* This file is auto-generated from PlaybackOverlayActivity.java. DO NOT MODIFY. */ + +/* + * Copyright (C) 2014 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 com.example.android.leanback; + +import android.support.v4.app.FragmentActivity; +import android.os.Bundle; + +public class PlaybackOverlaySupportActivity extends FragmentActivity +{ + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.playback_controls_support); + } +} diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlaySupportFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlaySupportFragment.java new file mode 100644 index 000000000..0a93027a6 --- /dev/null +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlaySupportFragment.java @@ -0,0 +1,172 @@ +/* This file is auto-generated from PlaybackOverlayFragment.java. DO NOT MODIFY. */ + +/* + * Copyright (C) 2014 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 com.example.android.leanback; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.Handler; +import android.support.v17.leanback.app.PlaybackControlGlue; +import android.support.v17.leanback.widget.Action; +import android.support.v17.leanback.widget.ArrayObjectAdapter; +import android.support.v17.leanback.widget.PlaybackControlsRow; +import android.support.v17.leanback.widget.PlaybackControlsRow.RepeatAction; +import android.support.v17.leanback.widget.PlaybackControlsRow.ThumbsUpAction; +import android.support.v17.leanback.widget.PlaybackControlsRow.ThumbsDownAction; +import android.support.v17.leanback.widget.PlaybackControlsRowPresenter; +import android.support.v17.leanback.widget.HeaderItem; +import android.support.v17.leanback.widget.PresenterSelector; +import android.support.v17.leanback.widget.Row; +import android.support.v17.leanback.widget.ListRow; +import android.support.v17.leanback.widget.Presenter; +import android.support.v17.leanback.widget.RowPresenter; +import android.support.v17.leanback.widget.ListRowPresenter; +import android.support.v17.leanback.widget.OnItemViewSelectedListener; +import android.support.v17.leanback.widget.OnItemViewClickedListener; +import android.support.v17.leanback.widget.ControlButtonPresenterSelector; +import android.support.v17.leanback.widget.SparseArrayObjectAdapter; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Toast; + +public class PlaybackOverlaySupportFragment extends android.support.v17.leanback.app.PlaybackOverlaySupportFragment { + private static final String TAG = "leanback.PlaybackControlsFragment"; + + /** + * Change this to choose a different overlay background. + */ + private static final int BACKGROUND_TYPE = PlaybackOverlaySupportFragment.BG_LIGHT; + + /** + * Change the number of related content rows. + */ + private static final int RELATED_CONTENT_ROWS = 3; + + /** + * Change this to select hidden + */ + private static final boolean SECONDARY_HIDDEN = false; + + private static final int ROW_CONTROLS = 0; + + private PlaybackControlSupportHelper mGlue; + private PlaybackControlsRowPresenter mPlaybackControlsRowPresenter; + private ListRowPresenter mListRowPresenter; + + private OnItemViewClickedListener mOnItemViewClickedListener = new OnItemViewClickedListener() { + @Override + public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, + RowPresenter.ViewHolder rowViewHolder, Row row) { + Log.i(TAG, "onItemClicked: " + item + " row " + row); + if (item instanceof Action) { + mGlue.onActionClicked((Action) item); + } + } + }; + + private OnItemViewSelectedListener mOnItemViewSelectedListener = new OnItemViewSelectedListener() { + @Override + public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, + RowPresenter.ViewHolder rowViewHolder, Row row) { + Log.i(TAG, "onItemSelected: " + item + " row " + row); + } + }; + + public SparseArrayObjectAdapter getAdapter() { + return (SparseArrayObjectAdapter) super.getAdapter(); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + Log.i(TAG, "onCreate"); + super.onCreate(savedInstanceState); + + setBackgroundType(BACKGROUND_TYPE); + setOnItemViewSelectedListener(mOnItemViewSelectedListener); + + createComponents(getActivity()); + } + + private void createComponents(Context context) { + mGlue = new PlaybackControlSupportHelper(context, this) { + @Override + public int getUpdatePeriod() { + int totalTime = getControlsRow().getTotalTime(); + if (getView() == null || getView().getWidth() == 0 || totalTime <= 0) { + return 1000; + } + return Math.max(16, totalTime / getView().getWidth()); + } + + @Override + protected void onRowChanged(PlaybackControlsRow row) { + if (getAdapter() == null) { + return; + } + int index = getAdapter().indexOf(row); + if (index >= 0) { + getAdapter().notifyArrayItemRangeChanged(index, 1); + } + } + }; + + mGlue.setOnItemViewClickedListener(mOnItemViewClickedListener); + + mPlaybackControlsRowPresenter = mGlue.createControlsRowAndPresenter(); + mPlaybackControlsRowPresenter.setSecondaryActionsHidden(SECONDARY_HIDDEN); + mListRowPresenter = new ListRowPresenter(); + + setAdapter(new SparseArrayObjectAdapter(new PresenterSelector() { + @Override + public Presenter getPresenter(Object object) { + if (object instanceof PlaybackControlsRow) { + return mPlaybackControlsRowPresenter; + } else if (object instanceof ListRow) { + return mListRowPresenter; + } + throw new IllegalArgumentException("Unhandled object: " + object); + } + })); + + // Add the controls row + getAdapter().set(ROW_CONTROLS, mGlue.getControlsRow()); + + // Add related content rows + for (int i = 0; i < RELATED_CONTENT_ROWS; ++i) { + ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new StringPresenter()); + listRowAdapter.add("Some related content"); + listRowAdapter.add("Other related content"); + HeaderItem header = new HeaderItem(i, "Row " + i); + getAdapter().set(ROW_CONTROLS + 1 + i, new ListRow(header, listRowAdapter)); + } + + } + + @Override + public void onStart() { + super.onStart(); + mGlue.setFadingEnabled(true); + mGlue.enableProgressUpdating(mGlue.hasValidMedia() && mGlue.isMediaPlaying()); + } + + @Override + public void onStop() { + mGlue.enableProgressUpdating(false); + super.onStop(); + } +} diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/RowsSupportActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/RowsSupportActivity.java new file mode 100644 index 000000000..ca4d0e144 --- /dev/null +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/RowsSupportActivity.java @@ -0,0 +1,60 @@ +/* This file is auto-generated from RowsActivity.java. DO NOT MODIFY. */ + +/* + * Copyright (C) 2014 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 com.example.android.leanback; + +import android.support.v4.app.FragmentActivity; +import android.content.Intent; +import android.os.Bundle; +import android.support.v17.leanback.R; +import android.support.v17.leanback.widget.BrowseFrameLayout; +import android.support.v17.leanback.widget.TitleHelper; +import android.support.v17.leanback.widget.TitleView; +import android.view.View; + +public class RowsSupportActivity extends FragmentActivity +{ + private RowsSupportFragment mRowsSupportFragment; + private TitleHelper mTitleHelper; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.rows_support); + + mRowsSupportFragment = (RowsSupportFragment) getSupportFragmentManager().findFragmentById( + R.id.main_rows_fragment); + + setupTitleFragment(); + } + + private void setupTitleFragment() { + TitleView titleView = (TitleView) findViewById(R.id.title); + titleView.setTitle("RowsSupportFragment"); + titleView.setOnSearchClickedListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(RowsSupportActivity.this, SearchSupportActivity.class); + startActivity(intent); + } + }); + + BrowseFrameLayout frameLayout = (BrowseFrameLayout) findViewById(R.id.rows_frame); + mTitleHelper = new TitleHelper(frameLayout, titleView); + frameLayout.setOnFocusSearchListener(mTitleHelper.getOnFocusSearchListener()); + mRowsSupportFragment.setTitleHelper(mTitleHelper); + } +} diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/RowsSupportFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/RowsSupportFragment.java new file mode 100644 index 000000000..e0a14031f --- /dev/null +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/RowsSupportFragment.java @@ -0,0 +1,120 @@ +/* This file is auto-generated from RowsFragment.java. DO NOT MODIFY. */ + +/* + * Copyright (C) 2014 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 com.example.android.leanback; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.support.v17.leanback.widget.TitleHelper; +import android.support.v17.leanback.widget.TitleView; +import android.support.v4.app.ActivityOptionsCompat; +import android.support.v17.leanback.R; +import android.support.v17.leanback.widget.ArrayObjectAdapter; +import android.support.v17.leanback.widget.HeaderItem; +import android.support.v17.leanback.widget.ImageCardView; +import android.support.v17.leanback.widget.ListRow; +import android.support.v17.leanback.widget.ListRowPresenter; +import android.support.v17.leanback.widget.OnItemViewClickedListener; +import android.support.v17.leanback.widget.OnItemViewSelectedListener; +import android.support.v17.leanback.widget.Presenter; +import android.support.v17.leanback.widget.Row; +import android.support.v17.leanback.widget.RowPresenter; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +public class RowsSupportFragment extends android.support.v17.leanback.app.RowsSupportFragment { + + private static final String TAG = "leanback.RowsSupportFragment"; + + private static final int NUM_ROWS = 10; + // Row heights default to wrap content + private static final boolean USE_FIXED_ROW_HEIGHT = false; + + private ArrayObjectAdapter mRowsAdapter; + private TitleHelper mTitleHelper; + + public void setTitleHelper(TitleHelper titleHelper) { + mTitleHelper = titleHelper; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + Log.i(TAG, "onCreate"); + super.onCreate(savedInstanceState); + + setupRows(); + setOnItemViewClickedListener(new ItemViewClickedListener()); + setOnItemViewSelectedListener(new OnItemViewSelectedListener() { + @Override + public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, + RowPresenter.ViewHolder rowViewHolder, Row row) { + Log.i(TAG, "onItemSelected: " + item + " row " + row); + if (mTitleHelper != null) { + mTitleHelper.showTitle(getAdapter() == null || getAdapter().size() == 0 || + getAdapter().get(0) == row); + } + } + }); + } + + private void setupRows() { + ListRowPresenter lrp = new ListRowPresenter(); + + if (USE_FIXED_ROW_HEIGHT) { + lrp.setRowHeight(CardPresenter.getRowHeight(getActivity())); + lrp.setExpandedRowHeight(CardPresenter.getExpandedRowHeight(getActivity())); + } + + mRowsAdapter = new ArrayObjectAdapter(lrp); + + // For good performance, it's important to use a single instance of + // a card presenter for all rows using that presenter. + final CardPresenter cardPresenter = new CardPresenter(); + + for (int i = 0; i < NUM_ROWS; ++i) { + ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter); + listRowAdapter.add(new PhotoItem("Hello world", R.drawable.gallery_photo_1)); + listRowAdapter.add(new PhotoItem("This is a test", R.drawable.gallery_photo_2)); + listRowAdapter.add(new PhotoItem("Android TV", R.drawable.gallery_photo_3)); + listRowAdapter.add(new PhotoItem("Leanback", R.drawable.gallery_photo_4)); + listRowAdapter.add(new PhotoItem("Hello world", R.drawable.gallery_photo_5)); + listRowAdapter.add(new PhotoItem("This is a test", R.drawable.gallery_photo_6)); + listRowAdapter.add(new PhotoItem("Android TV", R.drawable.gallery_photo_7)); + listRowAdapter.add(new PhotoItem("Leanback", R.drawable.gallery_photo_8)); + HeaderItem header = new HeaderItem(i, "Row " + i); + mRowsAdapter.add(new ListRow(header, listRowAdapter)); + } + + setAdapter(mRowsAdapter); + } + + private final class ItemViewClickedListener implements OnItemViewClickedListener { + @Override + public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, + RowPresenter.ViewHolder rowViewHolder, Row row) { + Intent intent = new Intent(getActivity(), DetailsSupportActivity.class); + intent.putExtra(DetailsSupportActivity.EXTRA_ITEM, (PhotoItem) item); + + Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation( + getActivity(), + ((ImageCardView)itemViewHolder.view).getMainImageView(), + DetailsSupportActivity.SHARED_ELEMENT_NAME).toBundle(); + getActivity().startActivity(intent, bundle); + } + } +} diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/SearchDetailsSupportActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/SearchDetailsSupportActivity.java new file mode 100644 index 000000000..c1d59b20c --- /dev/null +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/SearchDetailsSupportActivity.java @@ -0,0 +1,23 @@ +/* This file is auto-generated from SearchDetailsActivity.java. DO NOT MODIFY. */ + +/* + * Copyright (C) 2014 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 com.example.android.leanback; + +/** + * Same implementation as DetailsSupportActivity for different entries in AndroidManifest. + */ +public class SearchDetailsSupportActivity extends DetailsSupportActivity +{ +} diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/SearchSupportActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/SearchSupportActivity.java new file mode 100644 index 000000000..9ecdafedf --- /dev/null +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/SearchSupportActivity.java @@ -0,0 +1,67 @@ +/* This file is auto-generated from SearchActivity.java. DO NOT MODIFY. */ + +/* + * Copyright (C) 2014 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 com.example.android.leanback; + +import android.support.v4.app.FragmentActivity; +import android.content.Intent; +import android.os.Bundle; +import android.support.v17.leanback.app.SearchSupportFragment; +import android.support.v17.leanback.widget.SpeechRecognitionCallback; +import android.util.Log; + +public class SearchSupportActivity extends FragmentActivity +{ + private static final String TAG = "SearchSupportActivity"; + private static boolean DEBUG = true; + + /** If using internal speech recognizer, you must have RECORD_AUDIO permission */ + private static boolean USE_INTERNAL_SPEECH_RECOGNIZER = false; + private static final int REQUEST_SPEECH = 1; + + private SearchSupportFragment mFragment; + private SpeechRecognitionCallback mSpeechRecognitionCallback; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.search_support); + + mFragment = (SearchSupportFragment) getSupportFragmentManager().findFragmentById(R.id.search_fragment); + + if (!USE_INTERNAL_SPEECH_RECOGNIZER) { + mSpeechRecognitionCallback = new SpeechRecognitionCallback() { + @Override + public void recognizeSpeech() { + if (DEBUG) Log.v(TAG, "recognizeSpeech"); + startActivityForResult(mFragment.getRecognizerIntent(), REQUEST_SPEECH); + } + }; + mFragment.setSpeechRecognitionCallback(mSpeechRecognitionCallback); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (DEBUG) Log.v(TAG, "onActivityResult requestCode=" + requestCode + + " resultCode=" + resultCode + + " data=" + data); + if (requestCode == REQUEST_SPEECH && resultCode == RESULT_OK) { + mFragment.setSearchQuery(data, true); + } + } +} diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/SearchSupportFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/SearchSupportFragment.java new file mode 100644 index 000000000..35c5eb251 --- /dev/null +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/SearchSupportFragment.java @@ -0,0 +1,104 @@ +/* This file is auto-generated from SearchFragment.java. DO NOT MODIFY. */ + +package com.example.android.leanback; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.support.v4.app.ActivityOptionsCompat; +import android.support.v17.leanback.widget.ArrayObjectAdapter; +import android.support.v17.leanback.widget.HeaderItem; +import android.support.v17.leanback.widget.ImageCardView; +import android.support.v17.leanback.widget.ListRow; +import android.support.v17.leanback.widget.ListRowPresenter; +import android.support.v17.leanback.widget.ObjectAdapter; +import android.support.v17.leanback.widget.OnItemViewClickedListener; +import android.support.v17.leanback.widget.Presenter; +import android.support.v17.leanback.widget.Row; +import android.support.v17.leanback.widget.RowPresenter; +import android.text.TextUtils; +import android.util.Log; + +public class SearchSupportFragment extends android.support.v17.leanback.app.SearchSupportFragment + implements android.support.v17.leanback.app.SearchSupportFragment.SearchResultProvider { + private static final String TAG = "leanback.SearchSupportFragment"; + private static final int NUM_ROWS = 3; + private static final int SEARCH_DELAY_MS = 1000; + + private ArrayObjectAdapter mRowsAdapter; + private Handler mHandler = new Handler(); + private String mQuery; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter()); + + setBadgeDrawable(getActivity().getResources().getDrawable(R.drawable.ic_title)); + setTitle("Leanback Sample App"); + setSearchResultProvider(this); + setOnItemViewClickedListener(new ItemViewClickedListener()); + } + + @Override + public ObjectAdapter getResultsAdapter() { + return mRowsAdapter; + } + + @Override + public boolean onQueryTextChange(String newQuery) { + Log.i(TAG, String.format("Search Query Text Change %s", newQuery)); + mRowsAdapter.clear(); + loadQuery(newQuery); + return true; + } + + @Override + public boolean onQueryTextSubmit(String query) { + Log.i(TAG, String.format("Search Query Text Submit %s", query)); + mRowsAdapter.clear(); + loadQuery(query); + return true; + } + + private void loadQuery(String query) { + mQuery = query; + mHandler.removeCallbacks(mDelayedLoad); + if (!TextUtils.isEmpty(query) && !query.equals("nil")) { + mHandler.postDelayed(mDelayedLoad, SEARCH_DELAY_MS); + } + } + + private void loadRows() { + for (int i = 0; i < NUM_ROWS; ++i) { + ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new CardPresenter()); + listRowAdapter.add(new PhotoItem("Hello world", R.drawable.gallery_photo_1)); + listRowAdapter.add(new PhotoItem("This is a test", R.drawable.gallery_photo_2)); + HeaderItem header = new HeaderItem(i, mQuery + " results row " + i); + mRowsAdapter.add(new ListRow(header, listRowAdapter)); + } + } + + private Runnable mDelayedLoad = new Runnable() { + @Override + public void run() { + loadRows(); + } + }; + + private final class ItemViewClickedListener implements OnItemViewClickedListener { + @Override + public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, + RowPresenter.ViewHolder rowViewHolder, Row row) { + Intent intent = new Intent(getActivity(), DetailsSupportActivity.class); + intent.putExtra(DetailsSupportActivity.EXTRA_ITEM, (PhotoItem) item); + + Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation( + getActivity(), + ((ImageCardView)itemViewHolder.view).getMainImageView(), + DetailsSupportActivity.SHARED_ELEMENT_NAME).toBundle(); + getActivity().startActivity(intent, bundle); + } + } +} diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridFragment.java index 9ffaf66f5..fe664dd7a 100644 --- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridFragment.java +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridFragment.java @@ -15,6 +15,7 @@ package com.example.android.leanback; import android.content.Intent; import android.os.Bundle; +import android.os.Handler; import android.support.v17.leanback.widget.ArrayObjectAdapter; import android.support.v17.leanback.widget.Presenter; import android.support.v17.leanback.widget.RowPresenter; @@ -34,6 +35,7 @@ public class VerticalGridFragment extends android.support.v17.leanback.app.Verti private static final int NUM_COLUMNS = 3; private static final int NUM_ITEMS = 50; private static final int HEIGHT = 200; + private static final boolean TEST_ENTRANCE_TRANSITION = true; private static class Adapter extends ArrayObjectAdapter { public Adapter(StringPresenter presenter) { @@ -54,6 +56,25 @@ public class VerticalGridFragment extends android.support.v17.leanback.app.Verti setTitle("Leanback Vertical Grid Demo"); setupFragment(); + if (TEST_ENTRANCE_TRANSITION) { + // don't run entrance transition if fragment is restored. + if (savedInstanceState == null) { + prepareEntranceTransition(); + } + } + // simulates in a real world use case data being loaded two seconds later + new Handler().postDelayed(new Runnable() { + public void run() { + loadData(); + startEntranceTransition(); + } + }, 2000); + } + + private void loadData() { + for (int i = 0; i < NUM_ITEMS; i++) { + mAdapter.add(Integer.toString(i)); + } } private void setupFragment() { @@ -62,9 +83,6 @@ public class VerticalGridFragment extends android.support.v17.leanback.app.Verti setGridPresenter(gridPresenter); mAdapter = new Adapter(new StringPresenter()); - for (int i = 0; i < NUM_ITEMS; i++) { - mAdapter.add(Integer.toString(i)); - } setAdapter(mAdapter); setOnItemViewSelectedListener(new OnItemViewSelectedListener() { diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridSupportActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridSupportActivity.java new file mode 100644 index 000000000..0754fb872 --- /dev/null +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridSupportActivity.java @@ -0,0 +1,32 @@ +/* This file is auto-generated from VerticalGridActivity.java. DO NOT MODIFY. */ + +/* + * Copyright (C) 2014 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 com.example.android.leanback; + +import android.support.v4.app.FragmentActivity; +import android.os.Bundle; + +public class VerticalGridSupportActivity extends FragmentActivity +{ + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.vertical_grid_support); + // TODO: use BackgroundManager here + getWindow().setBackgroundDrawableResource(R.drawable.bg); + } +} diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridSupportFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridSupportFragment.java new file mode 100644 index 000000000..cd88f5a5b --- /dev/null +++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/VerticalGridSupportFragment.java @@ -0,0 +1,114 @@ +/* This file is auto-generated from VerticalGridFragment. DO NOT MODIFY. */ + +/* + * Copyright (C) 2014 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 com.example.android.leanback; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.support.v17.leanback.widget.ArrayObjectAdapter; +import android.support.v17.leanback.widget.Presenter; +import android.support.v17.leanback.widget.RowPresenter; +import android.support.v17.leanback.widget.VerticalGridPresenter; +import android.support.v17.leanback.widget.Row; +import android.support.v17.leanback.widget.OnItemViewClickedListener; +import android.support.v17.leanback.widget.OnItemViewSelectedListener; +import android.util.Log; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +public class VerticalGridSupportFragment extends android.support.v17.leanback.app.VerticalGridSupportFragment { + private static final String TAG = "leanback.VerticalGridSupportFragment"; + + private static final int NUM_COLUMNS = 3; + private static final int NUM_ITEMS = 50; + private static final int HEIGHT = 200; + private static final boolean TEST_ENTRANCE_TRANSITION = true; + + private static class Adapter extends ArrayObjectAdapter { + public Adapter(StringPresenter presenter) { + super(presenter); + } + public void callNotifyChanged() { + super.notifyChanged(); + } + } + private Adapter mAdapter; + + @Override + public void onCreate(Bundle savedInstanceState) { + Log.i(TAG, "onCreate"); + super.onCreate(savedInstanceState); + + setBadgeDrawable(getActivity().getResources().getDrawable(R.drawable.ic_title)); + setTitle("Leanback Vertical Grid Demo"); + + setupFragment(); + if (TEST_ENTRANCE_TRANSITION) { + // don't run entrance transition if fragment is restored. + if (savedInstanceState == null) { + prepareEntranceTransition(); + } + } + // simulates in a real world use case data being loaded two seconds later + new Handler().postDelayed(new Runnable() { + public void run() { + loadData(); + startEntranceTransition(); + } + }, 2000); + } + + private void loadData() { + for (int i = 0; i < NUM_ITEMS; i++) { + mAdapter.add(Integer.toString(i)); + } + } + + private void setupFragment() { + VerticalGridPresenter gridPresenter = new VerticalGridPresenter(); + gridPresenter.setNumberOfColumns(NUM_COLUMNS); + setGridPresenter(gridPresenter); + + mAdapter = new Adapter(new StringPresenter()); + setAdapter(mAdapter); + + setOnItemViewSelectedListener(new OnItemViewSelectedListener() { + @Override + public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, + RowPresenter.ViewHolder rowViewHolder, Row row) { + Log.i(TAG, "onItemSelected: " + item + " row " + row); + } + }); + + setOnItemViewClickedListener(new OnItemViewClickedListener() { + @Override + public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, + RowPresenter.ViewHolder rowViewHolder, Row row) { + Log.i(TAG, "onItemClicked: " + item + " row " + row); + mAdapter.callNotifyChanged(); + } + }); + setOnSearchClickedListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(getActivity(), SearchSupportActivity.class); + startActivity(intent); + } + }); + } +} |