1816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko/* 2816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Copyright (C) 2015 The Android Open Source Project 3816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 4816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Licensed under the Apache License, Version 2.0 (the "License"); 5816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * you may not use this file except in compliance with the License. 6816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * You may obtain a copy of the License at 7816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 8816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * http://www.apache.org/licenses/LICENSE-2.0 9816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 10816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Unless required by applicable law or agreed to in writing, software 11816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * distributed under the License is distributed on an "AS IS" BASIS, 12816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * See the License for the specific language governing permissions and 14816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * limitations under the License. 15816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 16816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 17816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkopackage com.android.tv.guide; 18816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 1965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.annotation.SuppressLint; 20816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.Context; 21816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.res.ColorStateList; 22816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.res.Resources; 23816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.graphics.drawable.Drawable; 24816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.graphics.drawable.LayerDrawable; 25816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.graphics.drawable.StateListDrawable; 26816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.os.Handler; 27816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.os.SystemClock; 28816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.text.SpannableStringBuilder; 29816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.text.Spanned; 30816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.text.TextUtils; 31816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.text.style.TextAppearanceSpan; 32816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.util.AttributeSet; 33816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.util.Log; 34816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.view.View; 35816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.view.ViewGroup; 36816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.widget.TextView; 3765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.widget.Toast; 38816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 391abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.ApplicationSingletons; 40816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.MainActivity; 41816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.R; 42816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.TvApplication; 43816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.analytics.Tracker; 44ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport com.android.tv.common.feature.CommonFeatures; 45816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.data.Channel; 461abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.dvr.DvrManager; 476ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.data.ScheduledRecording; 486ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.ui.DvrUiHelper; 49816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.guide.ProgramManager.TableEntry; 50d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport com.android.tv.util.ToastUtils; 51816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.util.Utils; 52816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 53816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.lang.reflect.InvocationTargetException; 54816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.concurrent.TimeUnit; 55816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 56816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkopublic class ProgramItemView extends TextView { 57816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final String TAG = "ProgramItemView"; 58816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 59816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final long FOCUS_UPDATE_FREQUENCY = TimeUnit.SECONDS.toMillis(1); 60816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int MAX_PROGRESS = 10000; // From android.widget.ProgressBar.MAX_VALUE 61816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 62816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // State indicating the focused program is the current program 63816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int[] STATE_CURRENT_PROGRAM = { R.attr.state_current_program }; 64816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 65816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // Workaround state in order to not use too much texture memory for RippleDrawable 66816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int[] STATE_TOO_WIDE = { R.attr.state_program_too_wide }; 67816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 68816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static int sVisibleThreshold; 69816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static int sItemPadding; 7065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private static int sCompoundDrawablePadding; 71816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static TextAppearanceSpan sProgramTitleStyle; 72816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static TextAppearanceSpan sGrayedOutProgramTitleStyle; 73816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static TextAppearanceSpan sEpisodeTitleStyle; 74816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static TextAppearanceSpan sGrayedOutEpisodeTitleStyle; 75816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 766ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private ProgramGuide mProgramGuide; 7765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private DvrManager mDvrManager; 78816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private TableEntry mTableEntry; 79816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private int mMaxWidthForRipple; 8007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko private int mTextWidth; 81816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 82816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // If set this flag disables requests to re-layout the parent view as a result of changing 83816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // this view, improving performance. This also prevents the parent view to lose child focus 84816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // as a result of the re-layout (see b/21378855). 85816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private boolean mPreventParentRelayout; 86816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 87816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final View.OnClickListener ON_CLICKED = new View.OnClickListener() { 88816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 89ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko public void onClick(final View view) { 90816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko TableEntry entry = ((ProgramItemView) view).mTableEntry; 912e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko if (entry == null) { 922e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko //do nothing 932e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko return; 942e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 951abddd9f6225298066094e20a6c29061b6af4590Nick Chalko ApplicationSingletons singletons = TvApplication.getSingletons(view.getContext()); 961abddd9f6225298066094e20a6c29061b6af4590Nick Chalko Tracker tracker = singletons.getTracker(); 97816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko tracker.sendEpgItemClicked(); 98d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko final MainActivity tvActivity = (MainActivity) view.getContext(); 99d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko final Channel channel = tvActivity.getChannelDataManager().getChannel(entry.channelId); 100816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (entry.isCurrentProgram()) { 101816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko view.postDelayed(new Runnable() { 102816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 103816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void run() { 104816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko tvActivity.tuneToChannel(channel); 105816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko tvActivity.hideOverlaysForTune(); 106816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 107ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko }, entry.getWidth() > ((ProgramItemView) view).mMaxWidthForRipple ? 0 108ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko : view.getResources() 109ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko .getInteger(R.integer.program_guide_ripple_anim_duration)); 1106ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } else if (entry.program != null && CommonFeatures.DVR.isEnabled(view.getContext())) { 11165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko DvrManager dvrManager = singletons.getDvrManager(); 11265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (entry.entryStartUtcMillis > System.currentTimeMillis() 11365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko && dvrManager.isProgramRecordable(entry.program)) { 1142e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko if (entry.scheduledRecording == null) { 1156ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko DvrUiHelper.checkStorageStatusAndShowErrorMessage(tvActivity, 1166ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko channel.getInputId(), new Runnable() { 1176ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko @Override 1186ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void run() { 1196ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko DvrUiHelper.requestRecordingFutureProgram(tvActivity, 1206ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko entry.program, false); 1216ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1226ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko }); 1232e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } else { 12465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko dvrManager.removeScheduledRecording(entry.scheduledRecording); 12565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko String msg = view.getResources().getString( 12665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko R.string.dvr_schedules_deletion_info, entry.program.getTitle()); 127d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko ToastUtils.show(view.getContext(), msg, Toast.LENGTH_SHORT); 1282e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 12965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } else { 130d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko ToastUtils.show(view.getContext(), view.getResources() 131d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko .getString(R.string.dvr_msg_cannot_record_program), Toast.LENGTH_SHORT); 132ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 133816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 134816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1352e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko }; 136ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko 137816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final View.OnFocusChangeListener ON_FOCUS_CHANGED = 138816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko new View.OnFocusChangeListener() { 139816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 140816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void onFocusChange(View view, boolean hasFocus) { 141816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (hasFocus) { 142816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko ((ProgramItemView) view).mUpdateFocus.run(); 143816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } else { 144816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Handler handler = view.getHandler(); 145816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (handler != null) { 146816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko handler.removeCallbacks(((ProgramItemView) view).mUpdateFocus); 147816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 148816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 149816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 150816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko }; 151816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 152816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private final Runnable mUpdateFocus = new Runnable() { 153816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 154816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void run() { 155816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko refreshDrawableState(); 156816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko TableEntry entry = mTableEntry; 1572e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko if (entry == null) { 1582e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko //do nothing 1592e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko return; 1602e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 161816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (entry.isCurrentProgram()) { 162816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Drawable background = getBackground(); 1636ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (!mProgramGuide.isActive() || mProgramGuide.isRunningAnimation()) { 1646ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko // If program guide is not active or is during showing/hiding, 1656ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko // the animation is unnecessary, skip it. 1666ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko background.jumpToCurrentState(); 1676ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 168816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko int progress = getProgress(entry.entryStartUtcMillis, entry.entryEndUtcMillis); 169816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko setProgress(background, R.id.reverse_progress, MAX_PROGRESS - progress); 170816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 171816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (getHandler() != null) { 172816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko getHandler().postAtTime(this, 173816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Utils.ceilTime(SystemClock.uptimeMillis(), FOCUS_UPDATE_FREQUENCY)); 174816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 175816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 176816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko }; 177816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 178816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public ProgramItemView(Context context) { 179816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko this(context, null); 180816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 181816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 182816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public ProgramItemView(Context context, AttributeSet attrs) { 183816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko this(context, attrs, 0); 184816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 185816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 186816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public ProgramItemView(Context context, AttributeSet attrs, int defStyle) { 187816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko super(context, attrs, defStyle); 1882e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko setOnClickListener(ON_CLICKED); 1892e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko setOnFocusChangeListener(ON_FOCUS_CHANGED); 19065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mDvrManager = TvApplication.getSingletons(getContext()).getDvrManager(); 191816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 192816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 193816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private void initIfNeeded() { 194816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (sVisibleThreshold != 0) { 195816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return; 196816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 197816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Resources res = getContext().getResources(); 198816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 199816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko sVisibleThreshold = res.getDimensionPixelOffset( 200816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko R.dimen.program_guide_table_item_visible_threshold); 201816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 202816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko sItemPadding = res.getDimensionPixelOffset(R.dimen.program_guide_table_item_padding); 20365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko sCompoundDrawablePadding = res.getDimensionPixelOffset( 20465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko R.dimen.program_guide_table_item_compound_drawable_padding); 20565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 20665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko ColorStateList programTitleColor = ColorStateList.valueOf(res.getColor( 20765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko R.color.program_guide_table_item_program_title_text_color, null)); 20865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko ColorStateList grayedOutProgramTitleColor = res.getColorStateList( 20965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko R.color.program_guide_table_item_grayed_out_program_text_color, null); 21065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko ColorStateList episodeTitleColor = ColorStateList.valueOf(res.getColor( 21165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko R.color.program_guide_table_item_program_episode_title_text_color, null)); 21265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko ColorStateList grayedOutEpisodeTitleColor = ColorStateList.valueOf(res.getColor( 21365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko R.color.program_guide_table_item_grayed_out_program_episode_title_text_color, 21465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko null)); 215816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko int programTitleSize = res.getDimensionPixelSize( 216816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko R.dimen.program_guide_table_item_program_title_font_size); 217816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko int episodeTitleSize = res.getDimensionPixelSize( 218816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko R.dimen.program_guide_table_item_program_episode_title_font_size); 219816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 220816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko sProgramTitleStyle = new TextAppearanceSpan(null, 0, programTitleSize, programTitleColor, 221816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko null); 222816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko sGrayedOutProgramTitleStyle = new TextAppearanceSpan(null, 0, programTitleSize, 223816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko grayedOutProgramTitleColor, null); 224816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko sEpisodeTitleStyle = new TextAppearanceSpan(null, 0, episodeTitleSize, episodeTitleColor, 225816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko null); 226816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko sGrayedOutEpisodeTitleStyle = new TextAppearanceSpan(null, 0, episodeTitleSize, 227816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko grayedOutEpisodeTitleColor, null); 228816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 229816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 230816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 231816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko protected void onFinishInflate() { 232ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko super.onFinishInflate(); 233816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko initIfNeeded(); 234816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 235816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 236816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 237816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko protected int[] onCreateDrawableState(int extraSpace) { 238816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mTableEntry != null) { 239816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko int states[] = super.onCreateDrawableState(extraSpace 240816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko + STATE_CURRENT_PROGRAM.length + STATE_TOO_WIDE.length); 241816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mTableEntry.isCurrentProgram()) { 242816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mergeDrawableStates(states, STATE_CURRENT_PROGRAM); 243816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 244816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mTableEntry.getWidth() > mMaxWidthForRipple) { 245816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mergeDrawableStates(states, STATE_TOO_WIDE); 246816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 247816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return states; 248816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 249816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return super.onCreateDrawableState(extraSpace); 250816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 251816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 252816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public TableEntry getTableEntry() { 253816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return mTableEntry; 254816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 255816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 25665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @SuppressLint("SwitchIntDef") 2576ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public void setValues(ProgramGuide programGuide, TableEntry entry, int selectedGenreId, 2586ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko long fromUtcMillis, long toUtcMillis, String gapTitle) { 2596ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mProgramGuide = programGuide; 260816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mTableEntry = entry; 261816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 262816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko ViewGroup.LayoutParams layoutParams = getLayoutParams(); 263816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko layoutParams.width = entry.getWidth(); 264816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko setLayoutParams(layoutParams); 265816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 266816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko String title = entry.program != null ? entry.program.getTitle() : null; 267816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko String episode = entry.program != null ? 268816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko entry.program.getEpisodeDisplayTitle(getContext()) : null; 269816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 270816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko TextAppearanceSpan titleStyle = sGrayedOutProgramTitleStyle; 271816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko TextAppearanceSpan episodeStyle = sGrayedOutEpisodeTitleStyle; 272816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 273816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (entry.getWidth() < sVisibleThreshold) { 274816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko setText(null); 275816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } else { 276816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (entry.isGap()) { 2772e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko title = gapTitle; 278816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko episode = null; 2792e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } else if (entry.hasGenre(selectedGenreId)) { 280816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko titleStyle = sProgramTitleStyle; 281816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko episodeStyle = sEpisodeTitleStyle; 282816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 2832e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko if (TextUtils.isEmpty(title)) { 2842e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko title = getResources().getString(R.string.program_title_for_no_information); 2852e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 286816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko SpannableStringBuilder description = new SpannableStringBuilder(); 287816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko description.append(title); 288816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (!TextUtils.isEmpty(episode)) { 289816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko description.append('\n'); 290816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 291816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // Add a 'zero-width joiner'/ZWJ in order to ensure we have the same line height for 292816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // all lines. This is a non-printing character so it will not change the horizontal 293816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // spacing however it will affect the line height. As we ensure the ZWJ has the same 294816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // text style as the title it will make sure the line height is consistent. 295816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko description.append('\u200D'); 296816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 297816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko int middle = description.length(); 298816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko description.append(episode); 299816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 300816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko description.setSpan(titleStyle, 0, middle, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 301816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko description.setSpan(episodeStyle, middle, description.length(), 302816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 303816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } else { 304816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko description.setSpan(titleStyle, 0, description.length(), 305816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 306816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 307816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko setText(description); 30865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 30965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko // Sets recording icons if needed. 31065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko int iconResId = 0; 31165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mTableEntry.scheduledRecording != null) { 31265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mDvrManager.isConflicting(mTableEntry.scheduledRecording)) { 313d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko iconResId = R.drawable.ic_warning_white_18dp; 31465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } else { 31565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko switch (mTableEntry.scheduledRecording.getState()) { 31665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko case ScheduledRecording.STATE_RECORDING_NOT_STARTED: 31765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko iconResId = R.drawable.ic_scheduled_recording; 31865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko break; 31965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko case ScheduledRecording.STATE_RECORDING_IN_PROGRESS: 32065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko iconResId = R.drawable.ic_recording_program; 32165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko break; 32265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 32365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 32465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 32565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko setCompoundDrawablePadding(iconResId != 0 ? sCompoundDrawablePadding : 0); 32665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, iconResId, 0); 327816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 32807b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); 32907b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko mTextWidth = getMeasuredWidth() - getPaddingStart() - getPaddingEnd(); 330816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // Maximum width for us to use a ripple 3312e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko mMaxWidthForRipple = GuideUtils.convertMillisToPixel(fromUtcMillis, toUtcMillis); 332816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 333816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 334816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 33565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Update programItemView to handle alignments of text. 33665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 33765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public void updateVisibleArea() { 33865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko View parentView = ((View) getParent()); 33965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (parentView == null) { 34065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return; 34165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 34265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (getLayoutDirection() == LAYOUT_DIRECTION_LTR) { 34365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko layoutVisibleArea(parentView.getLeft() - getLeft(), getRight() - parentView.getRight()); 34465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } else { 34565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko layoutVisibleArea(getRight() - parentView.getRight(), parentView.getLeft() - getLeft()); 34665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 34765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 34865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 34965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 350816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Layout title and episode according to visible area. 351816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 352816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Here's the spec. 353816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 1. Don't show text if it's shorter than 48dp. 354816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 2. Try showing whole text in visible area by placing and wrapping text, 355816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * but do not wrap text less than 30min. 356816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 3. Episode title is visible only if title isn't multi-line. 357816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 35865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param startOffset Offset of the start position from the enclosing view's start position. 35965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param endOffset Offset of the end position from the enclosing view's end position. 360816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 36165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private void layoutVisibleArea(int startOffset, int endOffset) { 362816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko int width = mTableEntry.getWidth(); 36365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko int startPadding = Math.max(0, startOffset); 36465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko int endPadding = Math.max(0, endOffset); 36507b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko int minWidth = Math.min(width, mTextWidth + 2 * sItemPadding); 36607b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko if (startPadding > 0 && width - startPadding < minWidth) { 36707b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko startPadding = Math.max(0, width - minWidth); 368816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 36965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (endPadding > 0 && width - endPadding < minWidth) { 37065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko endPadding = Math.max(0, width - minWidth); 37165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 372816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 37365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (startPadding + sItemPadding != getPaddingStart() 37465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko || endPadding + sItemPadding != getPaddingEnd()) { 375816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mPreventParentRelayout = true; // The size of this view is kept, no need to tell parent. 37665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko setPaddingRelative(startPadding + sItemPadding, 0, endPadding + sItemPadding, 0); 377816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mPreventParentRelayout = false; 378816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 379816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 380816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 3812e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko public void clearValues() { 382816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (getHandler() != null) { 383816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko getHandler().removeCallbacks(mUpdateFocus); 384816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 385816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 386816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko setTag(null); 3876ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mProgramGuide = null; 3882e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko mTableEntry = null; 389816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 390816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 391816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static int getProgress(long start, long end) { 392816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko long currentTime = System.currentTimeMillis(); 393816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (currentTime <= start) { 394816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return 0; 395816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } else if (currentTime >= end) { 396816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return MAX_PROGRESS; 397816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 398816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return (int) (((currentTime - start) * MAX_PROGRESS) / (end - start)); 399816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 400816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 401816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static void setProgress(Drawable drawable, int id, int progress) { 402816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (drawable instanceof StateListDrawable) { 403816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko StateListDrawable stateDrawable = (StateListDrawable) drawable; 404816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko for (int i = 0; i < getStateCount(stateDrawable); ++i) { 405816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko setProgress(getStateDrawable(stateDrawable, i), id, progress); 406816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 407816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } else if (drawable instanceof LayerDrawable) { 408816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko LayerDrawable layerDrawable = (LayerDrawable) drawable; 409816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko for (int i = 0; i < layerDrawable.getNumberOfLayers(); ++i) { 410816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko setProgress(layerDrawable.getDrawable(i), id, progress); 411816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (layerDrawable.getId(i) == id) { 412816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko layerDrawable.getDrawable(i).setLevel(progress); 413816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 414816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 415816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 416816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 417816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 418816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static int getStateCount(StateListDrawable stateListDrawable) { 419816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko try { 420816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Object stateCount = StateListDrawable.class.getDeclaredMethod("getStateCount") 421816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .invoke(stateListDrawable); 422816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return (int) stateCount; 423816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } catch (NoSuchMethodException|IllegalAccessException|IllegalArgumentException 424816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko |InvocationTargetException e) { 425816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Log.e(TAG, "Failed to call StateListDrawable.getStateCount()", e); 426816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return 0; 427816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 428816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 429816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 430816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static Drawable getStateDrawable(StateListDrawable stateListDrawable, int index) { 431816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko try { 432816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Object drawable = StateListDrawable.class 433816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .getDeclaredMethod("getStateDrawable", Integer.TYPE) 434816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .invoke(stateListDrawable, index); 435816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return (Drawable) drawable; 436816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } catch (NoSuchMethodException|IllegalAccessException|IllegalArgumentException 437816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko |InvocationTargetException e) { 438816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Log.e(TAG, "Failed to call StateListDrawable.getStateDrawable(" + index + ")", e); 439816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return null; 440816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 441816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 442816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 443816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Override 444816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void requestLayout() { 445816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (mPreventParentRelayout) { 446816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // Trivial layout, no need to tell parent. 447816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko forceLayout(); 448816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } else { 449816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko super.requestLayout(); 450816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 451816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 452816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko} 453