Android Sender UI 맞춤설정

색상을 설정하고 버튼, 텍스트, 미리보기 이미지의 스타일을 지정하고 표시할 버튼 유형을 선택하여 Cast 위젯 을 맞춤설정할 수 있습니다.

앱 테마 맞춤설정

이 예에서는 맞춤 색상, 소개 오버레이 스타일, 미니 컨트롤러 스타일, 확장된 컨트롤러 스타일을 정의할 수 있는 맞춤 테마 스타일 Theme.CastVideosTheme을 만듭니다.

<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Set AppCompat's color theming attrs -->
    <item name="colorPrimary">@color/primary</item>
    <item name="colorPrimaryDark">@color/primary_dark</item>
    <item name="colorAccent">@color/accent</item>
    <item name="android:textColorPrimary">@color/primary_text</item>
    <item name="android:textColorSecondary">@color/secondary_text</item>
    <item name="castIntroOverlayStyle">@style/CustomCastIntroOverlay</item>
    <item name="castMiniControllerStyle">@style/CustomCastMiniController</item>
    <item name="castExpandedControllerStyle">@style/CustomCastExpandedController</item>
</style>

위의 마지막 세 줄을 사용하면 이 테마의 일부로 소개 오버레이, 미니 컨트롤러, 확장된 컨트롤러와 관련된 스타일을 정의할 수 있습니다. 예는 다음 섹션에 포함되어 있습니다.

Cast 버튼 맞춤설정

앱의 테마에 맞춤 mediaRouteTheme를 추가하려면 다음 단계를 따르세요.

<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
  <!-- ... -->
  <item name="mediaRouteTheme">@style/CustomMediaRouterTheme</item>
</style>

맞춤 미디어 라우터 테마를 선언하고 맞춤 mediaRouteButtonStyle을 선언합니다.

<style name="CustomMediaRouterTheme" parent="Theme.MediaRouter">
  <item name="mediaRouteButtonStyle">@style/CustomMediaRouteButtonStyle</item>
</style>

<style name="CustomMediaRouteButtonStyle" parent="Widget.MediaRouter.Light.MediaRouteButton">
  <item name="mediaRouteButtonTint">#EEFF41</item>
</style>

setTint 지원 라이브러리 버전이 26.0.0보다 최신인 경우 사용해야 합니다. 이전 지원 라이브러리 버전의 경우 buttonTint 를 대신 사용하세요.

소개 오버레이 테마 맞춤설정

IntroductoryOverlay 클래스는 앱에서 맞춤 테마로 재정의할 수 있는 다양한 스타일 속성을 지원합니다. 이 예에서는 오버레이 위젯의 버튼과 제목의 텍스트 모양을 모두 재정의하는 방법을 보여줍니다.

<style name="CustomCastIntroOverlay" parent="CastIntroOverlay">
    <item name="castButtonTextAppearance">@style/TextAppearance.CustomCastIntroOverlay.Button</item>
    <item name="castTitleTextAppearance">@style/TextAppearance.CustomCastIntroOverlay.Title</item>
</style>
<style name="TextAppearance.CustomCastIntroOverlay.Button" parent="android:style/TextAppearance">
    <item name="android:textColor">#FFFFFF</item>
</style>
<style name="TextAppearance.CustomCastIntroOverlay.Title"parent="android:style/TextAppearance.Large">
    <item name="android:textColor">#FFFFFF</item>
</style>

미니 컨트롤러 맞춤설정

테마 맞춤설정

MiniControllerFragment 클래스는 앱에서 맞춤 테마로 재정의할 수 있는 다양한 스타일 속성을 지원합니다. 이 예에서는 미리보기 이미지 표시를 사용 설정하고, 부제목과 자막의 텍스트 모양을 모두 재정의하고, 색상을 설정하고, 버튼을 맞춤설정하는 방법을 보여줍니다.

<style name="CustomCastMiniController" parent="CastMiniController">
    <item name="castShowImageThumbnail">true</item>
    <item name="castTitleTextAppearance">@style/TextAppearance.AppCompat.Subhead</item>
    <item name="castSubtitleTextAppearance">@style/TextAppearance.AppCompat.Caption</item>
    <item name="castBackground">#FFFFFF</item>
    <item name="castProgressBarColor">#FFFFFF</item>
    <item name="castPlayButtonDrawable">@drawable/cast_ic_mini_controller_play</item>
    <item name="castPauseButtonDrawable">@drawable/cast_ic_mini_controller_pause</item>
    <item name="castStopButtonDrawable">@drawable/cast_ic_mini_controller_stop</item>
    <item name="castLargePlayButtonDrawable">@drawable/cast_ic_mini_controller_play_large</item>
    <item name="castLargePauseButtonDrawable">@drawable/cast_ic_mini_controller_pause_large</item>
    <item name="castLargeStopButtonDrawable">@drawable/cast_ic_mini_controller_stop_large</item>
    <item name="castSkipPreviousButtonDrawable">@drawable/cast_ic_mini_controller_skip_prev</item>
    <item name="castSkipNextButtonDrawable">@drawable/cast_ic_mini_controller_skip_next</item>
    <item name="castRewind30ButtonDrawable">@drawable/cast_ic_mini_controller_rewind30</item>
    <item name="castForward30ButtonDrawable">@drawable/cast_ic_mini_controller_forward30</item>
    <item name="castMuteToggleButtonDrawable">@drawable/cast_ic_mini_controller_mute</item>
    <item name="castClosedCaptionsButtonDrawable">@drawable/cast_ic_mini_controller_closed_caption</item
</style>

버튼 선택

MiniControllerFragment에는 앨범 아트와 두 개의 버튼 또는 앨범 아트가 채워지지 않은 경우 세 개의 컨트롤 버튼을 표시할 수 있는 슬롯이 세 개 있습니다.

SLOT  SLOT  SLOT
  1     2     3

기본적으로 프래그먼트에는 재생/일시중지 전환 버튼이 표시됩니다. 개발자는 castControlButtons 속성을 사용하여 표시할 버튼을 재정의할 수 있습니다. 지원되는 컨트롤 버튼은 ID 리소스로 정의됩니다:

버튼 유형 설명
@id/cast_button_type_empty 이 슬롯에 버튼을 배치하지 않습니다.
@id/cast_button_type_custom 맞춤 버튼
@id/cast_button_type_play_pause_toggle 재생과 일시중지 간에 전환합니다.
@id/cast_button_type_skip_previous 대기열의 이전 항목으로 건너뜁니다.
@id/cast_button_type_skip_next 대기열의 다음 항목으로 건너뜁니다.
@id/cast_button_type_rewind_30_seconds 재생을 30초 되감습니다.
@id/cast_button_type_forward_30_seconds 재생을 30초 앞으로 건너뜁니다.
@id/cast_button_type_mute_toggle 수신기의 음소거를 설정 및 해제합니다.
@id/cast_button_type_closed_caption 텍스트 및 오디오 트랙을 선택하는 대화상자를 엽니다.

다음은 왼쪽에서 오른쪽으로 앨범 아트, 재생/일시중지 전환 버튼, 앞으로 건너뛰기 버튼을 순서대로 사용하는 예입니다.

<array name="cast_mini_controller_control_buttons">
    <item>@id/cast_button_type_empty</item>
    <item>@id/cast_button_type_play_pause_toggle</item>
    <item>@id/cast_button_type_forward_30_seconds</item>
</array>
...
<fragment
    android:id="@+id/cast_mini_controller"
    ...
    app:castControlButtons="@array/cast_mini_controller_control_buttons"
    class="com.google.android.gms.cast.framework.media.widget.MiniControllerFragment">

경고: 이 배열에는 정확히 세 개의 항목이 포함되어야 합니다. 그렇지 않으면 런타임 예외가 발생합니다. 슬롯에 버튼을 표시하지 않으려면 @id/cast_button_type_empty를 사용하세요.

맞춤 버튼 추가

MiniControllerFragment는 '좋아요' 버튼과 같이 SDK에서 제공하지 않는 맞춤 컨트롤 버튼 추가를 지원합니다. 각 단계는

  1. MiniControllerFragmentcastControlButtons 속성에서 @id/cast_button_type_custom 을 사용하여 맞춤 버튼을 포함할 슬롯을 지정합니다.

  2. UIController의 서브클래스를 구현합니다. UIController에는 Cast 세션 또는 미디어 세션의 상태가 변경될 때 SDK에서 호출하는 메서드가 포함되어 있습니다. UIController 의 서브클래스는 ImageView 를 매개변수 중 하나로 가져와 필요에 따라 상태를 업데이트해야 합니다.

  3. MiniControllerFragment를 서브클래스화한 다음 onCreateView를 재정의하고 getButtonImageViewAt(int)를 호출하여 맞춤 버튼의 ImageView를 가져옵니다. 그런 다음 bindViewToUIController(View, UIController) 를 호출하여 뷰를 맞춤 UIController와 연결합니다.

  4. 맞춤 버튼의 작업을 처리하는 방법은 맞춤 작업 추가MediaIntentReceiver `MediaIntentReceiver`를 참고하세요.

    다음은 슬롯 2의 버튼을 UIController 이라고 하는 MyCustomUIController와 연결하는 예입니다.

// arrays.xml
<array name="cast_expanded_controller_control_buttons">
    <item>@id/cast_button_type_empty</item>
    <item>@id/cast_button_type_rewind_30_seconds</item>
    <item>@id/cast_button_type_custom</item>
    <item>@id/cast_button_type_empty</item>
</array>
Kotlin
// MyCustomUIController.kt
class MyCustomUIController(private val mView: View) : UIController() {
    override fun onMediaStatusUpdated() {
        // Update the state of mView based on the latest the media status.
        ...
        mView.visibility = View.INVISIBLE
        ...
    }
}

// MyMiniControllerFragment.kt
class MyMiniControllerFragment : MiniControllerFragment() {
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        super.onCreateView(inflater, container, savedInstanceState)
        val customButtonView = getButtonImageViewAt(2)
        val myCustomUiController = MyCustomUIController(customButtonView)
        uiMediaController.bindViewToUIController(customButtonView, myCustomUiController)
        ...
    }
}
Java
// MyCustomUIController.java
class MyCustomUIController extends UIController {
    private final View mView;

    public MyCustomUIController(View view) {
            mView = view;
    }

    @Override
    public onMediaStatusUpdated() {
        // Update the state of mView based on the latest the media status.
        ...
        mView.setVisibility(View.INVISIBLE);
        ...
    }
}

// MyMiniControllerFragment.java
class MyMiniControllerFragment extends MiniControllerFragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        ImageView customButtonView = getButtonImageViewAt(2);
        MyCustomUIController myCustomUiController = new MyCustomUIController(customButtonView);
        getUIMediaController().bindViewToUIController(customButtonView, myCustomUiController);
        ...
    }
}

확장된 컨트롤러 맞춤설정

테마 맞춤설정

확장된 컨트롤러의 활동에서 어두운 테마 툴바를 사용하는 경우 툴바에서 밝은 텍스트와 밝은 아이콘 색상을 사용하도록 테마를 설정할 수 있습니다.

<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="castExpandedControllerToolbarStyle">
        @style/ThemeOverlay.AppCompat.Dark.ActionBar
    </item>
</style>

확장된 컨트롤러에서 버튼을 그리는 데 사용되는 자체 이미지를 지정할 수 있습니다.

<style name="CustomCastExpandedController" parent="CastExpandedController">
    <item name="castButtonColor">@null</item>
    <item name="castPlayButtonDrawable">@drawable/cast_ic_expanded_controller_play</item>
    <item name="castPauseButtonDrawable">@drawable/cast_ic_expanded_controller_pause</item>
    <item name="castStopButtonDrawable">@drawable/cast_ic_expanded_controller_stop</item>
    <item name="castSkipPreviousButtonDrawable">@drawable/cast_ic_expanded_controller_skip_previous</item>
    <item name="castSkipNextButtonDrawable">@drawable/cast_ic_expanded_controller_skip_next</item>
    <item name="castRewind30ButtonDrawable">@drawable/cast_ic_expanded_controller_rewind30</item>
    <item name="castForward30ButtonDrawable">@drawable/cast_ic_expanded_controller_forward30</item>
</style>

버튼 선택

확장된 컨트롤러의 활동에는 컨트롤 버튼을 표시하는 슬롯이 5개 있습니다. 가운데 슬롯에는 항상 재생/일시중지 전환 버튼이 표시되며 구성할 수 없습니다. 다른 네 개의 슬롯은 왼쪽에서 오른쪽으로 발신자 앱에서 구성할 수 있습니다.

SLOT  SLOT  PLAY/PAUSE  SLOT  SLOT
  1     2     BUTTON      3     4

기본적으로 활동에는 왼쪽에서 오른쪽으로 이 네 개의 슬롯에 자막 버튼, 이전 항목으로 건너뛰기 버튼, 다음 항목으로 건너뛰기 버튼, 음소거 전환 버튼이 표시됩니다. 개발자는 castControlButtons 속성을 사용하여 슬롯에 표시할 버튼을 재정의할 수 있습니다. 지원되는 컨트롤 버튼 목록은 미니 컨트롤러 버튼의 버튼 유형과 동일한 ID 리소스로 정의됩니다.

다음은 되감기 버튼을 두 번째 슬롯에, 앞으로 건너뛰기 버튼을 세 번째 슬롯에 배치하고 첫 번째와 마지막 슬롯을 비워 두는 예입니다.

// arrays.xml
<array name="cast_expanded_controller_control_buttons">
    <item>@id/cast_button_type_empty</item>
    <item>@id/cast_button_type_rewind_30_seconds</item>
    <item>@id/cast_button_type_forward_30_seconds</item>
    <item>@id/cast_button_type_empty</item>
</array>
...
// styles.xml
<style name="Theme.MyTheme">
    <item name="castExpandedControllerStyle">
        @style/CustomCastExpandedController
    </item>
</style>
...
<style name="CustomCastExpandedController" parent="CastExpandedController">
    <item name="castControlButtons">
        @array/cast_expanded_controller_control_buttons
    </item>
</style>

배열에는 정확히 네 개의 항목이 포함되어야 합니다. 그렇지 않으면 런타임 예외가 발생합니다. 슬롯에 버튼을 표시하지 않으려면 @id/cast_button_type_empty를 사용하세요. CastContext 는 이 활동의 수명 주기와 프레젠테이션을 관리할 수 있습니다.

맞춤 버튼 추가

ExpandedControllerActivity는 '좋아요' 버튼과 같이 SDK에서 제공하지 않는 맞춤 컨트롤 버튼 추가를 지원합니다. 각 단계는

  1. ExpandedControllerActivitycastControlButtons 속성에서 @id/cast_button_type_custom 을 사용하여 맞춤 버튼을 포함할 슬롯을 지정합니다. 그런 다음 getButtonImageViewAt(int) 을 사용하여 맞춤 버튼의 ImageView 을 가져올 수 있습니다.

  2. UIController의 서브클래스를 구현합니다. UIController 에는 Cast 세션 또는 미디어 세션의 상태가 변경될 때 SDK에서 호출하는 메서드가 포함되어 있습니다. UIController의 서브클래스는 ImageView를 매개변수 중 하나로 가져와 필요에 따라 상태를 업데이트해야 합니다.

  3. ExpandedControllerActivity를 서브클래스화한 다음 onCreate 를 재정의하고 getButtonImageViewAt(int) 를 호출하여 버튼의 뷰 객체를 가져옵니다. 그런 다음 bindViewToUIController(View, UIController) 를 호출하여 뷰를 맞춤 UIController와 연결합니다.

  4. 맞춤 버튼의 작업을 처리하는 방법은 MediaIntentReceiver 맞춤 작업 추가 를 참고하세요.

다음은 슬롯 2의 버튼을 UIController이라고 하는 MyCustomUIController와 연결하는 예입니다.

// arrays.xml
<array name="cast_expanded_controller_control_buttons">
    <item>@id/cast_button_type_empty</item>
    <item>@id/cast_button_type_rewind_30_seconds</item>
    <item>@id/cast_button_type_custom</item>
    <item>@id/cast_button_type_empty</item>
</array>
Kotlin
// MyCustomUIController.kt
class MyCustomUIController(private val mView: View) : UIController() {
    override fun onMediaStatusUpdated() {
        // Update the state of mView based on the latest the media status.
        ...
        mView.visibility = View.INVISIBLE
        ...
    }
}

// MyExpandedControllerActivity.kt
internal class MyExpandedControllerActivity : ExpandedControllerActivity() {
    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val customButtonView = getButtonImageViewAt(2)
        val myCustomUiController = MyCustomUIController(customButtonView)
        uiMediaController.bindViewToUIController(customButtonView, myCustomUiController)
        ...
    }
}
Java
// MyCustomUIController.java
class MyCustomUIController extends UIController {
    private final View mView;

    public MyCustomUIController(View view) {
        mView = view;
    }

    @Override
    public onMediaStatusUpdated() {
        // Update the state of mView based on the latest the media status.
        ...
        mView.setVisibility(View.INVISIBLE);
        ...
    }
}

// MyExpandedControllerActivity.java
class MyExpandedControllerActivity extends ExpandedControllerActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ImageView customButtonView = getButtonImageViewAt(2);
        MyCustomUIController myCustomUiController = new MyCustomUIController(customButtonView);
        getUIMediaController().bindViewToUIController(customButtonView, myCustomUiController);
        ...
    }
}