16

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.

altocumulus
  • 21,179
  • 13
  • 61
  • 84
AnZ
  • 1,040
  • 24
  • 54
  • 3
    @prudhvi, Unfortunately no. But I solved this in a bit tricky way. I've created 2 `MediaControllers` which act like one and set different anchors for them. And the trick was in hiding one of them when orientation changes. So in landscape mode I had controlled linked to `VideoSurface` and in portrait mode controller was anchored to `LinearLayout` with buttons and stuff. – AnZ Nov 12 '15 at 14:26
  • Are you doing this in conjunction with the standard Android MediaPlayer? – Doug Stevenson Feb 11 '16 at 05:47
  • @Doug Stevenson, I was using Google Exo Player as far as I remember. But it's quite similar to standard one. – AnZ Feb 11 '16 at 08:45

1 Answers1

2

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.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441