158b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell/* 258b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell * Copyright (C) 2016 The Android Open Source Project 358b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell * 458b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell * Licensed under the Apache License, Version 2.0 (the "License"); 558b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell * you may not use this file except in compliance with the License. 658b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell * You may obtain a copy of the License at 758b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell * 858b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell * http://www.apache.org/licenses/LICENSE-2.0 958b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell * 1058b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell * Unless required by applicable law or agreed to in writing, software 1158b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell * distributed under the License is distributed on an "AS IS" BASIS, 1258b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1358b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell * See the License for the specific language governing permissions and 1458b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell * limitations under the License 1558b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell */ 1658b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell 1758b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellpackage com.google.android.leanbackjank.ui; 1858b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell 1958b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport android.content.Intent; 20f30fe4064a0b3934ba4e780feac8c11e20e267f4Bryan Cassellimport android.content.res.Resources; 2158b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport android.net.Uri; 2258b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport android.os.Bundle; 2358b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport android.support.v17.leanback.app.BackgroundManager; 2458b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport android.support.v17.leanback.app.BrowseFragment; 2558b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport android.support.v17.leanback.widget.ArrayObjectAdapter; 2658b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport android.support.v17.leanback.widget.HeaderItem; 2758b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport android.support.v17.leanback.widget.ListRow; 2858b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport android.support.v17.leanback.widget.ListRowPresenter; 2958b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport android.support.v17.leanback.widget.Presenter; 3058b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport android.support.v17.leanback.widget.PresenterSelector; 31f30fe4064a0b3934ba4e780feac8c11e20e267f4Bryan Cassellimport android.support.v17.leanback.widget.ShadowOverlayHelper; 32a3eaac19490539262eff7832eff880566c57cafcAurimas Liutikasimport android.support.v4.content.res.ResourcesCompat; 3358b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell 3458b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport com.google.android.leanbackjank.IntentDefaults; 3558b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport com.google.android.leanbackjank.IntentKeys; 3658b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport com.google.android.leanbackjank.R; 3758b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport com.google.android.leanbackjank.data.VideoProvider; 3858b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport com.google.android.leanbackjank.model.VideoInfo; 3958b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport com.google.android.leanbackjank.presenter.CardPresenter; 4058b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport com.google.android.leanbackjank.presenter.GridItemPresenter; 4158b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport com.google.android.leanbackjank.presenter.HeaderItemPresenter; 4258b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell 4358b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport java.util.HashMap; 4458b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport java.util.List; 4558b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellimport java.util.Map; 4658b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell 4758b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell/** 4858b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell * Main class to show BrowseFragment with header and rows of videos 4958b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell */ 5058b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassellpublic class MainFragment extends BrowseFragment { 5158b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell 5258b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell private BackgroundManager mBackgroundManager; 5358b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell private ArrayObjectAdapter mRowsAdapter; 5458b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell 5558b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell @Override 5658b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell public void onActivityCreated(Bundle savedInstanceState) { 5758b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell super.onActivityCreated(savedInstanceState); 5858b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell 5958b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell // Define defaults. 6058b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell int categoryCount = IntentDefaults.CATEGORY_COUNT; 6158b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell int entriesPerCat = IntentDefaults.ENTRIES_PER_CATEGORY; 6258b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell boolean disableShadows = IntentDefaults.DISABLE_SHADOWS; 6358b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell int cardWidth = IntentDefaults.CARD_WIDTH; 6458b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell int cardHeight = IntentDefaults.CARD_HEIGHT; 65734bc41ce2a1f549a972bfda05ede02d969ebefbDaniel Cardenas int whichVideo = IntentDefaults.WHICH_VIDEO; 6658b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell boolean useSingleBitmap = IntentDefaults.USE_SINGLE_BITMAP; 6758b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell 6858b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell Intent intent = getActivity().getIntent(); 6958b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell if (intent.getExtras() != null) { 7058b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell categoryCount = intent.getIntExtra(IntentKeys.CATEGORY_COUNT, categoryCount); 7158b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell entriesPerCat = intent.getIntExtra(IntentKeys.ENTRIES_PER_CATEGORY, entriesPerCat); 7258b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell disableShadows = intent.getBooleanExtra(IntentKeys.DISABLE_SHADOWS, disableShadows); 7358b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell cardWidth = intent.getIntExtra(IntentKeys.CARD_WIDTH, cardWidth); 7458b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell cardHeight = intent.getIntExtra(IntentKeys.CARD_HEIGHT, cardHeight); 75734bc41ce2a1f549a972bfda05ede02d969ebefbDaniel Cardenas whichVideo = intent.getIntExtra(IntentKeys.WHICH_VIDEO, whichVideo); 7658b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell useSingleBitmap = intent.getBooleanExtra(IntentKeys.USE_SINGLE_BITMAP, useSingleBitmap); 7758b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell } 7858b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell 7958b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell loadVideoData(categoryCount, entriesPerCat, disableShadows, useSingleBitmap, cardWidth, 8058b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell cardHeight); 8158b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell setBackground(); 8258b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell setupUIElements(); 8358b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell 84734bc41ce2a1f549a972bfda05ede02d969ebefbDaniel Cardenas if (whichVideo != IntentKeys.NO_VIDEO) { 85734bc41ce2a1f549a972bfda05ede02d969ebefbDaniel Cardenas int resource = 0; 86734bc41ce2a1f549a972bfda05ede02d969ebefbDaniel Cardenas /* For info on how to generate videos see: 87734bc41ce2a1f549a972bfda05ede02d969ebefbDaniel Cardenas * https://docs.google.com/document/d/1HV8O-Nm4rc2DwVwiZmT4Wa9pf8XttWndg9saGncTRGw 88734bc41ce2a1f549a972bfda05ede02d969ebefbDaniel Cardenas */ 89734bc41ce2a1f549a972bfda05ede02d969ebefbDaniel Cardenas if (whichVideo == IntentKeys.VIDEO_2160P_60FPS) { 90734bc41ce2a1f549a972bfda05ede02d969ebefbDaniel Cardenas resource = R.raw.bbb_sunflower_2160p_60fps; 91734bc41ce2a1f549a972bfda05ede02d969ebefbDaniel Cardenas } else if (whichVideo == IntentKeys.VIDEO_1080P_60FPS) { 92734bc41ce2a1f549a972bfda05ede02d969ebefbDaniel Cardenas resource = R.raw.testvideo_1080p_60fps; 93734bc41ce2a1f549a972bfda05ede02d969ebefbDaniel Cardenas } else if (whichVideo == IntentKeys.VIDEO_480P_60FPS) { 94734bc41ce2a1f549a972bfda05ede02d969ebefbDaniel Cardenas resource = R.raw.bbb_480p; 95f69640504837ec25d9eef68338782673a9874742Enrico Bianco } else if (whichVideo == IntentKeys.VIDEO_360P_60FPS) { 96f69640504837ec25d9eef68338782673a9874742Enrico Bianco resource = R.raw.bbb_360p; 97734bc41ce2a1f549a972bfda05ede02d969ebefbDaniel Cardenas } 98a3eaac19490539262eff7832eff880566c57cafcAurimas Liutikas Uri uri = Uri.parse("android.resource://" + getActivity().getPackageName() + "/" 99734bc41ce2a1f549a972bfda05ede02d969ebefbDaniel Cardenas + resource); 100a3eaac19490539262eff7832eff880566c57cafcAurimas Liutikas Intent videoIntent = new Intent(Intent.ACTION_VIEW, uri, getActivity(), 10158b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell VideoActivity.class); 10258b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell startActivity(videoIntent); 10358b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell } 10458b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell } 10558b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell 10658b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell private void setBackground() { 10758b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell mBackgroundManager = BackgroundManager.getInstance(getActivity()); 10858b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell mBackgroundManager.attach(getActivity().getWindow()); 10958b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell mBackgroundManager.setDrawable( 110a3eaac19490539262eff7832eff880566c57cafcAurimas Liutikas ResourcesCompat.getDrawable(getResources(), R.drawable.default_background, null)); 11158b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell } 11258b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell 11358b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell private void setupUIElements() { 114a3eaac19490539262eff7832eff880566c57cafcAurimas Liutikas setBadgeDrawable(ResourcesCompat.getDrawable( 115a3eaac19490539262eff7832eff880566c57cafcAurimas Liutikas getActivity().getResources(), R.drawable.app_banner, null)); 11658b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell // Badge, when set, takes precedent over title 11758b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell setTitle(getString(R.string.browse_title)); 11858b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell setHeadersState(HEADERS_ENABLED); 11958b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell setHeadersTransitionOnBackEnabled(true); 12058b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell // set headers background color 121a3eaac19490539262eff7832eff880566c57cafcAurimas Liutikas setBrandColor(ResourcesCompat.getColor(getResources(), R.color.jank_yellow, null)); 12258b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell // set search icon color 123a3eaac19490539262eff7832eff880566c57cafcAurimas Liutikas setSearchAffordanceColor( 124a3eaac19490539262eff7832eff880566c57cafcAurimas Liutikas ResourcesCompat.getColor(getResources(), R.color.search_opaque, null)); 12558b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell 12658b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell setHeaderPresenterSelector(new PresenterSelector() { 12758b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell @Override 12858b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell public Presenter getPresenter(Object o) { 12958b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell return new HeaderItemPresenter(); 13058b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell } 13158b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell }); 13258b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell } 13358b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell 13458b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell private void loadVideoData(int categoryCount, int entriesPerCat, boolean disableShadows, 13558b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell boolean useSingleBitmap, int cardWidth, int cardHeight) { 136f30fe4064a0b3934ba4e780feac8c11e20e267f4Bryan Cassell ListRowPresenter listRowPresenter = new ListRowPresenter() { 137f30fe4064a0b3934ba4e780feac8c11e20e267f4Bryan Cassell @Override 138f30fe4064a0b3934ba4e780feac8c11e20e267f4Bryan Cassell protected ShadowOverlayHelper.Options createShadowOverlayOptions() { 139f30fe4064a0b3934ba4e780feac8c11e20e267f4Bryan Cassell Resources res = getResources(); 140f30fe4064a0b3934ba4e780feac8c11e20e267f4Bryan Cassell ShadowOverlayHelper.Options options = new ShadowOverlayHelper.Options(); 141f30fe4064a0b3934ba4e780feac8c11e20e267f4Bryan Cassell options.dynamicShadowZ(res.getDimension(R.dimen.shadow_unfocused_z), 142f30fe4064a0b3934ba4e780feac8c11e20e267f4Bryan Cassell res.getDimension(R.dimen.shadow_focused_z)); 143f30fe4064a0b3934ba4e780feac8c11e20e267f4Bryan Cassell return options; 144f30fe4064a0b3934ba4e780feac8c11e20e267f4Bryan Cassell } 145f30fe4064a0b3934ba4e780feac8c11e20e267f4Bryan Cassell }; 14658b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell listRowPresenter.setShadowEnabled(!disableShadows); 14701a567100c9b8120d590e9e9f4cc6395ab0159feDake Gu // see b/64451726, leanback bug causes child rounded corner is incorrectly disabled when 14801a567100c9b8120d590e9e9f4cc6395ab0159feDake Gu // shadow is disabled. To make the test data consistent and comparable, by default treat 14901a567100c9b8120d590e9e9f4cc6395ab0159feDake Gu // the rounded corner option same as shadow option. 15001a567100c9b8120d590e9e9f4cc6395ab0159feDake Gu boolean disableRoundedCorner = disableShadows; 15101a567100c9b8120d590e9e9f4cc6395ab0159feDake Gu listRowPresenter.enableChildRoundedCorners(!disableRoundedCorner); 15258b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell mRowsAdapter = new ArrayObjectAdapter(listRowPresenter); 15358b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell HashMap<String, List<VideoInfo>> data = VideoProvider.buildMedia(categoryCount, 154a3eaac19490539262eff7832eff880566c57cafcAurimas Liutikas entriesPerCat, cardWidth, cardHeight, getActivity(), useSingleBitmap); 15558b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell CardPresenter cardPresenter = new CardPresenter(cardWidth, cardHeight); 15658b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell 15758b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell int i = 0; 15858b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell for (Map.Entry<String, List<VideoInfo>> entry : data.entrySet()) { 15958b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter); 16058b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell for (VideoInfo videoInfo : entry.getValue()) { 16158b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell listRowAdapter.add(videoInfo); 16258b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell } 16358b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell HeaderItem header = new HeaderItem(i++, entry.getKey()); 16458b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell mRowsAdapter.add(new ListRow(header, listRowAdapter)); 16558b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell } 16658b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell 16758b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell ArrayObjectAdapter settingsListAdapter = new ArrayObjectAdapter(new GridItemPresenter()); 16858b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell for (int j = 0; j < entriesPerCat; j++) { 16958b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell settingsListAdapter.add("Settings " + j); 17058b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell } 17158b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell HeaderItem settingsHeader = new HeaderItem(i++, "Settings"); 17258b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell mRowsAdapter.add(new ListRow(settingsHeader, settingsListAdapter)); 17358b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell 17458b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell setAdapter(mRowsAdapter); 17558b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell } 17658b7bbb83053e664ada2e1ace49f8960dfecdbfdBryan Cassell} 177