3

I have an ex0player in a RecyclerView of CardViews. The height of the exoplayer needs to be changed programmatically based on the height of the video contained. This height value is passed returned from the API call in pixels. Here is the layout of the ViewHolder:

<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    app:cardCornerRadius="10dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">


    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/communityPlayableCl"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
       >


        <com.google.android.exoplayer2.ui.PlayerView
            android:id="@+id/toroPlayerView"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:background="@color/transparent"
            android:visibility="invisible"
            app:controller_layout_id="@layout/v_player_controls"
            app:keep_content_on_player_reset="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/communityPlayableIv"
            app:player_layout_id="@layout/toro_exo_player_view"
            app:resize_mode="zoom"
            app:show_buffering="when_playing"
            app:shutter_background_color="@android:color/transparent"
            app:surface_type="texture_view"
            app:use_controller="false" />

        <androidx.appcompat.widget.AppCompatImageView
            android:id="@+id/communityPlayableIv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:adjustViewBounds="true"
            android:background="@color/black"
            android:scaleType="centerCrop"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="parent"
            tools:layout_editor_absoluteY="0dp"
            tools:src="@color/alpha_grey" />

        <androidx.appcompat.widget.AppCompatImageView
            android:id="@+id/volumeIv"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_gravity="bottom|end"
            android:padding="15dp"
            android:src="@drawable/ic_volume_off"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent" />


    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.cardview.widget.CardView>

Here is how I am adjusting the height and aspect ratio:

   if (model.mediaHeight != 0 && model.mediaHeight != null ) {
            communityPlayableCl.requestLayout()
            communityPlayableCl.layoutParams.height = model.mediaHeight

        }



    val constraintSet = ConstraintSet()
    constraintSet.clone(communityPlayableCl)
    constraintSet.setDimensionRatio(itemView.id,model.mediaAspectRatio)
    constraintSet.applyTo(communityPlayableCl)

This crops the top and bottom of a 640x640 video

andrewedgar
  • 797
  • 1
  • 12
  • 46
  • instead of changing height via layout params why don't you try to change the aspect ratio like app:layout_constraintDimensionRatio="w,:" – Gautam May 22 '20 at 16:50
  • Edited. Now it's cropping the top and bottom of a 640x640 video – andrewedgar May 26 '20 at 16:42
  • can you try setting the harcoded aspect ratio as 1:1 for the same video and check for debugging purpose – Gautam May 26 '20 at 18:17

2 Answers2

0

You can get the dimensions from the video using something like this. I'd add a try/catch around Uri.parse as well, which will fail if the file cannot be parsed.

Pair<Integer, Integer> getMediaDimensions(File file, Context context) {
    if (!file.exists()) return null;
    MediaMetadataRetriever retriever = new MediaMetadataRetriever();
    retriever.setDataSource(context, Uri.parse(file.getAbsolutePath()));
    int width = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
    int height = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
    retriever.release();

    return new Pair<>(width, height);
}

From there, you can either manually calculate and set new height/width after calculating the ratio. Alternatively, use a ConstraintLayout as the player's container and set its layout_constraintDimensionRatio to something like H,1:1, and replace each 1 with your width/height.

If you're using Kotlin, you can follow this post to adjust accordingly, and add a reuseable extension.

Gibolt
  • 42,564
  • 15
  • 187
  • 127
  • Edited my post. The aspect ration and dimensions get passed with the model. Still not showing up properly, though. – andrewedgar May 26 '20 at 16:55
  • Is `model.mediaAspectRatio` a valid string? You should just hardcode what is expected and test that first. Also, why are you setting the height of the ConstraintLayout? Remove the line forcing layout height – Gibolt May 26 '20 at 17:37
  • Yes, I'm printing it out. I tested with a harcoded value too. If I don't change the layout height programatically, every view collapses. – andrewedgar May 26 '20 at 18:32
  • Did you try adding app:layout_constraintDimensionRatio="H,3:1" or something similar to the XML instead? It shouldn't collapse. You should also set setDimensionRatio on toroPlayerView.id. Maybe also try requestLayout after the constraintSet change. – Gibolt May 26 '20 at 18:45
0

I ended up setting the dimensions of the view manually using the passed aspect ratio

andrewedgar
  • 797
  • 1
  • 12
  • 46