Meghan Gill
VideoView Fun: Gardener Goes Wild
Updated: Jun 21, 2021
This week I made a simple app with two activities. The goal for this project was to replicate the XML layout of two simple screens. I gave it a fun spin by inserting a home video. Check it out to the left.
Let's look at the XML of the first screen. Below is the code for activity_main.xml. You can see the VideoView is nested inside of a FrameLayout. FrameLayout should be used when you need to block off a portion of the screen for just one layout(performance will not be heavily impacted if you only nest one child). I have chosen to place the VideoView inside of the FrameLayout so that I could round its corners.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:layout_marginBottom="10dp"
android:layout_marginTop="32dp">
<TextView
android:id="@+id/textViewVideoHeading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:fontFamily="sans-serif-medium"
android:text="Continue watching"
android:textStyle="bold"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textSize="32sp"
android:typeface="normal"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:id="@+id/videoContainer"
android:layout_marginTop="16dp"
android:layout_width="match_parent"
android:layout_height="200dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textViewVideoHeading"
android:background="@drawable/rounded_corners">
<VideoView
android:id="@+id/videoDadWithShears"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal" />
</FrameLayout>
<TextView
android:id="@+id/textViewInteractionDesign"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/videoContainer"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:text="Interaction Design"
android:textColor="@color/sky_blue"
android:textSize="18sp"
android:textStyle="bold"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:typeface="normal" />
<TextView
android:id="@+id/textViewPrototyping"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:text="Learn Prototyping"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textSize="28sp"
android:typeface="normal"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textViewInteractionDesign" />
<ImageView
android:id="@+id/imageViewPurpleRectangle"
android:layout_width="200dp"
android:layout_height="125dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textViewPrototyping"
android:layout_marginTop="60dp"
android:background="@drawable/purple_rounded_corner"
android:contentDescription="Patrick Gill is a gardener on the rampage" />
<TextView
android:id="@+id/textViewDesign"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/imageViewPurpleRectangle"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:text="Design"
android:textColor="@color/cornflower"
android:textSize="18sp"
android:textStyle="bold"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:typeface="normal" />
<TextView
android:id="@+id/textViewHeuristics"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:text="Usability Heuristics"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textSize="18sp"
android:typeface="normal"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textViewDesign" />
<ImageView
android:id="@+id/imageViewMainYellowArrow"
android:layout_width="50dp"
android:layout_height="50dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="@id/imageViewPurpleRectangle"
app:layout_constraintStart_toEndOf="@id/imageViewPurpleRectangle"
android:layout_marginEnd="16dp"
app:layout_constraintTop_toTopOf="@id/imageViewPurpleRectangle"
android:clickable="true"
android:background="@drawable/circle"
android:src="@drawable/ic_baseline_arrow_forward_ios_24"
android:scaleType="centerInside"
android:elevation="6dp"
android:focusable="true" />
</androidx.constraintlayout.widget.ConstraintLayout>

This XML creates a simple layout. I have rounded the corners of the FrameLayout videoContainer and imageViewPurpleRectangle with custom made Drawable Resource Files. The imageViewMainYellowArrow acts as a button to go to the next activity. I have also created a a new Drawable Resource File to make it circular.
Now, let's add the video. The only way to do that is in code. I'm working in Java. The first step is the create a raw folder to house your video. I'm using a mp4. Go to the resource or res folder, right click and choose New > Android Resource Directory. Name the directory raw and choose the Resource Type raw. Now you can add your video to the folder.
The code for my MainActivity is below. For a step by step tutorial on creating a simple videoView I used https://abhiandroid.com/ui/videoview.
package com.meghangillwrites.interactiondesignxmlpractice;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.MediaController;
import android.widget.Toast;
import android.widget.VideoView;
import static android.view.Gravity.CENTER_VERTICAL;
public class MainActivity extends AppCompatActivity {
private FrameLayout videoViewContainer;
private VideoView simpleVideoView;
private MediaController mediaController;
private ImageView clickableArrow;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
videoViewContainer = findViewById(R.id.videoContainer);
simpleVideoView = findViewById(R.id.videoDadWithShears);
clickableArrow = findViewById(R.id.imageViewMainYellowArrow);
if(mediaController == null){
mediaController = new MediaController(this);
mediaController.setAnchorView(simpleVideoView);
}
videoViewContainer.setClipToOutline(true);
simpleVideoView.setMediaController(mediaController);
simpleVideoView.setVideoURI(Uri.parse("android.resource://" + getPackageName()
+ "/" + R.raw.dad_with_shears));
simpleVideoView.requestFocus();
simpleVideoView.setZOrderOnTop(false); does
simpleVideoView.start();
simpleVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
Toast toast = Toast.makeText(getApplicationContext(), "Patrick Gill on the rampage...", Toast.LENGTH_LONG);
toast.setGravity(Gravity.TOP, 0, 0);
toast.show();
}
});
simpleVideoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Toast toast = Toast.makeText(getApplicationContext(), "Oops an error occurred while playing the video!", Toast.LENGTH_LONG);
toast.setGravity(Gravity.TOP, 0, 0);
toast.show();
return false;
}
});
clickableArrow.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
nextActivity();
}
}
);
}
private void nextActivity() {
Intent intent = new Intent(this,PhoneNumberActivity.class);
startActivity(intent);
}
}
MediaController is a view containing controls for a MediaPlayer. Typically contains the buttons like "Play/Pause", "Rewind", "Fast Forward" and a progress slider. It takes care of synchronizing the controls with the state of the MediaPlayer.
.setAnchorView() attaches the mediaController to the view.
.setMediaController() sets the controller with controls for video playback (pause, play, etc). It's a method of VideoView.
*A note on Toasts:
The default position of toasts is the bottom center of the screen. In Android devices running API 28 and below you can customize the positioning of the toast using gravity. In APIs 30 and above you cannot use .setGravity() to customize a toast's position. Instead, using a Snackbar is recommended.