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>

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

전송 버튼 맞춤설정

앱 테마에 맞춤 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

기본적으로 활동은 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);
        ...
    }
}