PipControlsView.java revision 83fbf18ced2a386dff5fd9bb30fa5d8229cb517a
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.systemui.pip.tv; 18 19import android.content.Context; 20import android.media.session.MediaController; 21import android.media.session.PlaybackState; 22import android.view.View; 23import android.view.Gravity; 24import android.view.LayoutInflater; 25import android.widget.LinearLayout; 26import android.util.AttributeSet; 27 28import com.android.systemui.R; 29 30import static android.media.session.PlaybackState.ACTION_PAUSE; 31import static android.media.session.PlaybackState.ACTION_PLAY; 32 33 34/** 35 * A view containing PIP controls including fullscreen, close, and media controls. 36 */ 37public class PipControlsView extends LinearLayout { 38 /** 39 * An interface to listen user action. 40 */ 41 public abstract static interface Listener { 42 /** 43 * Called when an user clicks close PIP button. 44 */ 45 public abstract void onClosed(); 46 }; 47 48 private MediaController mMediaController; 49 50 final PipManager mPipManager = PipManager.getInstance(); 51 Listener mListener; 52 53 private PipControlButtonView mFullButtonView; 54 private PipControlButtonView mCloseButtonView; 55 private PipControlButtonView mPlayPauseButtonView; 56 57 private PipControlButtonView mFocusedChild; 58 59 private MediaController.Callback mMediaControllerCallback = new MediaController.Callback() { 60 @Override 61 public void onPlaybackStateChanged(PlaybackState state) { 62 updatePlayPauseView(); 63 } 64 }; 65 66 private final PipManager.MediaListener mPipMediaListener = new PipManager.MediaListener() { 67 @Override 68 public void onMediaControllerChanged() { 69 updateMediaController(); 70 } 71 }; 72 73 private final OnFocusChangeListener mFocusChangeListener = new OnFocusChangeListener() { 74 @Override 75 public void onFocusChange(View view, boolean hasFocus) { 76 if (hasFocus) { 77 mFocusedChild = (PipControlButtonView) view; 78 } else if (mFocusedChild == view) { 79 mFocusedChild = null; 80 } 81 } 82 }; 83 84 public PipControlsView(Context context) { 85 this(context, null, 0, 0); 86 } 87 88 public PipControlsView(Context context, AttributeSet attrs) { 89 this(context, attrs, 0, 0); 90 } 91 92 public PipControlsView(Context context, AttributeSet attrs, int defStyleAttr) { 93 this(context, attrs, defStyleAttr, 0); 94 } 95 96 public PipControlsView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 97 super(context, attrs, defStyleAttr, defStyleRes); 98 LayoutInflater inflater = (LayoutInflater) getContext() 99 .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 100 inflater.inflate(R.layout.tv_pip_controls, this); 101 102 setOrientation(LinearLayout.HORIZONTAL); 103 setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL); 104 } 105 106 @Override 107 public void onFinishInflate() { 108 super.onFinishInflate(); 109 110 mFullButtonView = findViewById(R.id.full_button); 111 mFullButtonView.setOnFocusChangeListener(mFocusChangeListener); 112 mFullButtonView.setOnClickListener(new View.OnClickListener() { 113 @Override 114 public void onClick(View v) { 115 mPipManager.movePipToFullscreen(); 116 } 117 }); 118 119 mCloseButtonView = findViewById(R.id.close_button); 120 mCloseButtonView.setOnFocusChangeListener(mFocusChangeListener); 121 mCloseButtonView.setOnClickListener(new View.OnClickListener() { 122 @Override 123 public void onClick(View v) { 124 mPipManager.closePip(); 125 if (mListener != null) { 126 mListener.onClosed(); 127 } 128 } 129 }); 130 131 mPlayPauseButtonView = findViewById(R.id.play_pause_button); 132 mPlayPauseButtonView.setOnFocusChangeListener(mFocusChangeListener); 133 mPlayPauseButtonView.setOnClickListener(new View.OnClickListener() { 134 @Override 135 public void onClick(View v) { 136 if (mMediaController == null || mMediaController.getPlaybackState() == null) { 137 return; 138 } 139 long actions = mMediaController.getPlaybackState().getActions(); 140 int state = mMediaController.getPlaybackState().getState(); 141 if (mPipManager.getPlaybackState() == PipManager.PLAYBACK_STATE_PAUSED) { 142 mMediaController.getTransportControls().play(); 143 } else if (mPipManager.getPlaybackState() == PipManager.PLAYBACK_STATE_PLAYING) { 144 mMediaController.getTransportControls().pause(); 145 } 146 // View will be updated later in {@link mMediaControllerCallback} 147 } 148 }); 149 } 150 151 @Override 152 public void onAttachedToWindow() { 153 super.onAttachedToWindow(); 154 updateMediaController(); 155 mPipManager.addMediaListener(mPipMediaListener); 156 } 157 158 @Override 159 public void onDetachedFromWindow() { 160 super.onDetachedFromWindow(); 161 mPipManager.removeMediaListener(mPipMediaListener); 162 if (mMediaController != null) { 163 mMediaController.unregisterCallback(mMediaControllerCallback); 164 } 165 } 166 167 private void updateMediaController() { 168 MediaController newController = mPipManager.getMediaController(); 169 if (mMediaController == newController) { 170 return; 171 } 172 if (mMediaController != null) { 173 mMediaController.unregisterCallback(mMediaControllerCallback); 174 } 175 mMediaController = newController; 176 if (mMediaController != null) { 177 mMediaController.registerCallback(mMediaControllerCallback); 178 } 179 updatePlayPauseView(); 180 } 181 182 private void updatePlayPauseView() { 183 int state = mPipManager.getPlaybackState(); 184 if (state == PipManager.PLAYBACK_STATE_UNAVAILABLE) { 185 mPlayPauseButtonView.setVisibility(View.GONE); 186 } else { 187 mPlayPauseButtonView.setVisibility(View.VISIBLE); 188 if (state == PipManager.PLAYBACK_STATE_PLAYING) { 189 mPlayPauseButtonView.setImageResource(R.drawable.ic_pause_white); 190 mPlayPauseButtonView.setText(R.string.pip_pause); 191 } else { 192 mPlayPauseButtonView.setImageResource(R.drawable.ic_play_arrow_white); 193 mPlayPauseButtonView.setText(R.string.pip_play); 194 } 195 } 196 } 197 198 /** 199 * Resets to initial state. 200 */ 201 public void reset() { 202 mFullButtonView.reset(); 203 mCloseButtonView.reset(); 204 mPlayPauseButtonView.reset(); 205 mFullButtonView.requestFocus(); 206 } 207 208 /** 209 * Sets the {@link Listener} to listen user actions. 210 */ 211 public void setListener(Listener listener) { 212 mListener = listener; 213 } 214 215 /** 216 * Returns the focused control button view to animate focused button. 217 */ 218 PipControlButtonView getFocusedButton() { 219 return mFocusedChild; 220 } 221} 222