Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change MediaController position on rotation

I'm trying to change MediaController's anchor dynamically on orientation changes. And after all my attempts this isn't working as needed.

Perhaps you could point out my mistake.

In a few words:

Portrait mode:

  1. weightSum = 1.
  2. SurfaceView weight: 0.4
  3. MediaController and HorizontalScrollView weight: 0.6
  4. MediaController always visible and not hiding

Landscape mode:

  1. SurfaceView weight: 0.0 (full screen)

  2. MediaControlls = View.Gone (I need to change its anchor to SurfaceView. And popup onTouch. But how??)


CODE CODE:

player.xml:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:keepScreenOn="true"
    tools:context="tenkol.design.com.imbrecords.ActivityExoPlayer"
    android:weightSum="1"
    android:orientation="vertical">

    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/surface_wrapper"
        android:layout_weight="0.4">

        <com.google.android.exoplayer.VideoSurfaceView
            android:id="@+id/surface_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center" />

        <View
            android:id="@+id/shutter"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/black" />
    </FrameLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_weight="0.6"
        android:orientation="vertical">

        <FrameLayout
            android:id="@+id/controls_wrapper"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="2dp">
        </FrameLayout>

        <HorizontalScrollView
            android:id="@+id/myGallery"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="0dp">

            <LinearLayout
                android:id="@+id/channelsScrollView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:orientation="horizontal"
                android:paddingBottom="5dp"
                android:paddingTop="5dp"
                />
        </HorizontalScrollView>

    </LinearLayout>

</LinearLayout>

code with transformation:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    if (Global.getScreenOrientation(this) == Configuration.ORIENTATION_LANDSCAPE) {
        //hide action bar
        getSupportActionBar().hide();
        if (myGallery != null) {
            //hide HorizontalScrollView
            myGallery.setVisibility(View.GONE);
        }
        //make surface fullscreen
        surfaceWrapper.setLayoutParams(new LinearLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT, 0f));
        controlsWrapper.setLayoutParams(new LinearLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT, 0f));
        //hide mediaController
        mc.hide();
        controlsWrapper.setVisibility(View.GONE);
    }
    if (Global.getScreenOrientation(this) == Configuration.ORIENTATION_PORTRAIT) {
        //and here restore everything
        getSupportActionBar().show();
        if (myGallery != null) {
            myGallery.setVisibility(View.VISIBLE);
        }

        surfaceWrapper.setLayoutParams(new LinearLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.FILL_PARENT, 0.4f));
        controlsWrapper.setLayoutParams(new LinearLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT, 0.6f));
        controlsWrapper.setVisibility(View.VISIBLE);
    }
}

What I tried:

1) When Landscape: create another mediaController and bind to root view(doesn't work):

  mediaController.setAnchorView(root);
  mediaController.setMediaPlayer(player.getPlayerControl());
  mediaController.setEnabled(true);
  mediaController.show(3);

2) When Landscape: change the anchor of previous MediaController (Nah).

  mc.setAnchorView(surfaceWrapper);
  mc.show(3);

3) interface surfaceChanged (still no):

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    if (Global.getScreenOrientation(this) == Configuration.ORIENTATION_LANDSCAPE) {
        mc.setAnchorView(surfaceWrapper);
        mc.setMediaPlayer(player.getPlayerControl());
        mc.setVisibility(View.VISIBLE);
        mc.show(3);
    }
}

So how can I change the MediaController's anchor to SurfaceView dynamically in LANDSCAPE mode?

P.S. Tell if some more code needed.

like image 829
AnZ Avatar asked Apr 07 '15 17:04

AnZ


1 Answers

Since you're overriding onConfigurationChanged, I assume that means the activity is not allowing Android to manage its orientation changes and instead choosing to do everything itself. This is normally not a great idea, and you're currently facing the pain of that decision. :-(

If I may make a recommendation: let Android manage the lifecycle of your activity, and use different layouts (e.g. layout-land/views.xml and layout-port/views.xml). This will allow you to express your layouts naturally in the XML without having to make crazy code changes.

You probably about to say: But I want my ExoPlayer not to have to stop, prepare and restart on every orientation change. The good news is that there is a way to work around this.

Just create a single ExoPlayer, prepare it at first load, and keep using that one instance (stored in a static or some other singleton) with each new activity instance. You can detach the old activity from it and reattach a new one when it's ready.

If ExoPlayer works similarly to MediaPlayer, then this should all work OK.

like image 68
Doug Stevenson Avatar answered Sep 29 '22 04:09

Doug Stevenson