Android 발신자 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>

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

전송 버튼 맞춤설정

맞춤 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>

지원 라이브러리 버전이 26.0.0 이상인 경우 setTint를 사용해야 합니다. 이전 지원 라이브러리 버전의 경우 대신 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에는 앨범 아트를 표시할 수 있는 슬롯 3개, 버튼 2개 또는 앨범 아트가 채워지지 않은 경우 컨트롤 버튼 3개가 있습니다.

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">

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

맞춤 버튼 추가

MiniControllerFragment는 '좋아요' 버튼과 같이 SDK에서 제공하지 않는 맞춤 컨트롤 버튼을 추가할 수 있습니다. 단계는 다음과 같습니다.

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

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

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

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

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

// 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)
        ...
    }
}
자바
// 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개 있습니다. 가운데 슬롯은 항상 재생/일시중지 전환 버튼을 표시하며 구성할 수 없습니다. 나머지 4개 슬롯은 발신기 앱에서 왼쪽에서 오른쪽으로 구성할 수 있습니다.

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>

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

맞춤 버튼 추가

ExpandedControllerActivity는 SDK에서 제공하지 않는 맞춤 컨트롤 버튼(예: '좋아요' 버튼 추가)을 추가할 수 있습니다. 단계는 다음과 같습니다.

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

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

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

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

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

// 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)
        ...
    }
}
자바
// 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);
        ...
    }
}