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