Android进阶——巧借自定义VideoView实现Activity的动态视频背景_CrazyMo_的博客-程序员资料_动态创建 videoview

技术标签: 自定义VideoView  Android 进阶  VideoView自适应全屏幕  # Android自定义View  Activity视频背景  Android  Activity动态背景  

引言

话说这个Activity 动态背景我第一次是在一个菠菜App上看到的,当时感觉逼格很高,最近正好用到项目中,而且好像好久没有写关于UI这些“有趣”的文章啦,这篇文章就简单小结下,其实实现动态背景这并不是唯一的方案,还有其他的方式。

一、VideoView

1、VideoView概述

VideoView继承自SurfaceView 并实现了MediaController.MediaPlayerControl接口, 是一种可以直接加载并播放来自多种路径(比如 resources 、raw、 content providers)的视频文件资源的官方控件,可以像其他任何普通控件一样在任意布局中声明并使用,有了他使得一些简单播放视频的工作变得简单(但是不适合应用在大型复杂项目等专业的播放音视频的项目中)。需要注意的是VideoView不会自动保存播放状态和播放位置等,所以当进入到后台前,若需要再再次返回时恢复 所选曲目或通过addSubtitleSource()添加的任何字幕轨道等状态, 应在Activity.onSaveInstanceState(Bundle)和Activity.onRestoreInstanceState(Bundle)中自行保存和恢复这些内容。

2、VideoView 重要的成员方法

名称 说明
void addSubtitleSource(InputStream is, MediaFormat format) 添加外部字幕文件流
boolean isPlaying() 判断是否正在播放
int getCurrentPosition() 获取当前播放位置
void seekTo(int msec) 跳转到指定位置
void setOnCompletionListener(MediaPlayer.OnCompletionListener l) 设置一个在媒体文件加载并准备就绪时调用的回调。
void setOnCompletionListener(MediaPlayer.OnCompletionListener l) 设置一个在媒体文件播放完毕,到达终点时调用的回调
void setOnErrorListener(MediaPlayer.OnErrorListener l) 设置一个在媒体文件播放或者设置时发生错误调用的回调
void setVideoPath(String path) 设置播放视频的字符串路径
void setVideoURI(Uri uri, Map<String, String> headers) 使用指定的头部设置播放视频的URi
void setVideoURI(Uri uri) 设置视频的URi
void setMediaController(MediaController controller) 设置视频播放控制器

二、自定义VideoView实现动态视频背景

其实原理很简单就是利用VideoView控件播放指定的一个视频文件,并把之设置为全屏幕的(非必须要求结合自己的需求来定),然后在生命周期方法中利用提供的各种方法进行监听。

1、 继承VedioView 重写onMeasure方法,为了更好的自适应全屏幕

package com.crazymo.activitybganim.widget;

import android.content.Context;
import android.media.MediaPlayer;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.VideoView;

/**
 * Auther: Crazy.Mo on 2018/8/24 14:35
 * Summary:继承VideoView实现自适应全屏幕
 */
public class CustomVideoView extends VideoView {
    
    public CustomVideoView(Context context) {
    
        this(context,null);
    }

    public CustomVideoView(Context context, AttributeSet attrs) {
    
        this(context, attrs,0);
    }

    public CustomVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
    
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    
        //重新计算高度
        int width = getDefaultSize(0, widthMeasureSpec);
        int height = getDefaultSize(0, heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

    /**
     * @param pPreparedListener 设置一个在媒体文件加载并准备就绪时调用的回调。
     */
    @Override
    public void setOnPreparedListener(MediaPlayer.OnPreparedListener pPreparedListener) {
    
        super.setOnPreparedListener(pPreparedListener);
    }

    /**
     * @param pCompletionListener 设置一个在媒体文件播放完毕,到达终点时调用的回调。
     */
    @Override
    public void setOnCompletionListener(MediaPlayer.OnCompletionListener pCompletionListener) {
    
        super.setOnCompletionListener(pCompletionListener);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
    
        return super.onKeyDown(keyCode, event);
    }
}

  • 在布局文件中声明自定义的VedioView
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:id="@+id/activity_main"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
    >

    <com.crazymo.activitybganim.widget.CustomVideoView
        android:id="@+id/videoview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        >
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:src="@mipmap/ic_launcher_round"/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="60sp"
            android:textColor="#f00"
            android:text="视频背景上的TextView"/>
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="60sp"
            android:textColor="#00f000"
            android:hint="视频背景上的EditText"/>
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Button Click"
            android:onClick="test"/>
    </LinearLayout>

</FrameLayout>
  • 在Activity中初始化VideoView并在对应的周期方法中进行对应的监听处理
package com.crazymo.activitybganim;

import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;

import com.crazymo.activitybganim.widget.CustomVideoView;

public class MainActivity extends AppCompatActivity {
    
    //创建播放视频的控件对象
    private CustomVideoView mVideoView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
        super.onCreate(savedInstanceState);
        setFullScreen();
        setContentView(R.layout.activity_main);
        initView();
    }

    private void setFullScreen() {
    
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }

    @Override
    protected void onRestart() {
    
        //返回时重新加载视频,防止退出或返回时视频黑屏
        initView();
        super.onRestart();
    }

    @Override
    protected void onPause() {
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    
            mVideoView.stopNestedScroll();
        }
        super.onPause();
    }

    //防止锁屏或者切出的时候,音乐在播放
    @Override
    protected void onStop() {
    
        if(mVideoView !=null) {
    
            mVideoView.stopPlayback();
        }
        super.onStop();
    }

    private void initView() {
    
        mVideoView =  findViewById(R.id.videoview);
        //设置将要播放视频文件的加载路径仅支持 3gp、MP4、avi
        mVideoView.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/" +R.raw.bg));//此处播放/res/raw下,也可以播放其他路径的调用对应的方法设置即可
        mVideoView.requestFocus();
        mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
    
            @Override
            public void onPrepared(MediaPlayer mp) {
    
                if (mp.isPlaying()) {
    
                    mp.stop();
                    mp.release();
                    mp = new MediaPlayer();
                }
                mp.setVolume(0f, 0f);//设置0,0为静音时
                mp.setLooping(true);
                mp.start();
            }
        });
        mVideoView.setFocusable(false);
        mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
    
            @Override
            public void onCompletion(MediaPlayer mediaPlayer) {
    
                mVideoView.start();
            }
        });
    }

    public void test(View view) {
    
        Toast.makeText(this,"在背景视频上点击按钮",Toast.LENGTH_SHORT).show();
    }
}

在这里插入图片描述

源码传送门码云传送门

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/CrazyMo_/article/details/83060324

智能推荐

监听器的使用_criller的博客-程序员资料

监听器的使用 1.1概述 监听器: 主要是用来监听特定对象的创建或销毁、属性的变化的! 是一个实现特定接口的普通java类!对象: 自己创建自己用 (不用监听) 别人创建自己用 (需要监听)Servlet中哪些对象需要监听? request / session / servletContext 分别对应的是request监听器、sess

简历上的“熟练掌握 RPC”,到底是个什么水平?_Java思维导图的博客-程序员资料

最近一朋友和我吐槽,说看到几个不错的简历,但一面试发现水分太大,让我想起去年面的一个高级开发,简历上写着“熟练掌握 RPC 框架”,我就试探着问了几个问题“大概说下 RPC 框架的核心原理...

一起来学SpringBoot(十一)优雅的整合Quartz_MelancholyCat的博客-程序员资料

Quartz是一个功能丰富的开源作业调度库,几乎可以集成在任何Java应用程序中 - 从最小的独立应用程序到最大的电子商务系统。Quartz可用于创建简单或复杂的计划,以执行数十,数百甚至数万个作业; 将任务定义为标准Java组件的作业,这些组件可以执行几乎任何可以编程的程序。Quartz Scheduler包含许多企业级功能,例如支持JTA事务和集群。springboot在2.x后加入了quar...

linux如何将网卡的名称改成wlan0_小肥侠123的博客-程序员资料

现象描述和解决方案当我们执行ifconfig命令来查看无线网卡的时候,发现无线网卡的名称不是wlan0,而是类似于wlx23747cdd23这种很长的名字,如下图所示:要向让无线网卡名称变回wlan0,其实很简单,首先执行如下命令,将80-net-setup-link.rules文件从/lib/udev/rules.d/目录复制到 /etc/udev/rules.d/ 目录下:cp /lib/udev/rules.d/80-net-setup-link.rules /etc/udev/rule

java实现pdf的生成下载打印,java生成pdf电子账单,java生成pdf合同模板_JaredYang_csdn的博客-程序员资料

java实现pdf的生成下载打印,java生成pdf电子账单,java生成pdf合同模板,Itext编辑pdf,java使用itext

Oracle 使用序列创建自增字段_sixi_yanyan的博客-程序员资料_创建一个自增序列字段的表

在Oracle中sequence就是所谓的序列号,每次取的时候它会自动增加,一般用在需要按序列号排序的地方。 1、Create Sequence 你首先要有create sequence或者create any sequence权限 Sql代码 CREATE SEQUENCE SEQ_EMP INCREMENT BY 1 -- 每次加几个 START WITH    在Oracle中sequenc

随便推点

Java获取rtsp视频流,实现rtsp流预览功能,并将视频流每帧保存成图片_江斌先生的博客-程序员资料_java rtsp取流

先展示maven依赖吧,就一个javacv&lt;dependency&gt; &lt;groupId&gt;org.bytedeco&lt;/groupId&gt; &lt;artifactId&gt;javacv-platform&lt;/artifactId&gt; &lt;version&gt;1.5.1&lt;/version&gt; &lt;type&gt;pom&lt;/type&gt; &lt;/dependency&gt;然后就是测试类publi

freemarker+jstl自定义标签实现动态表单的显示_刘正权的博客-程序员资料_freemarker 自定义表单

上一篇文章中,已经对freemarker做了简单的了解;动态表单的概念大家也应该不陌生了,在《浅析动态表单》文章中已经做了一定的分析;jstl自定义标签也比较熟悉了,在此之前已经使用多次了。今天我们就使用freemarker+jstl自定义标签实现动态表单的显示。

Java中URLEncoder.encode对应的JS解码_cloudsandstars的博客-程序员资料

结论:Java的URLEncoder.encode(data, &quot;UTF-8&quot;)对应的JS解码操作为:unescape(decodeURI(data));背景知识:JS的相关操作escape、encodeURI、encodeURIComponent1)escape待叙2)encodeURI待叙3)encodeURIComponent待叙Java的URLEncoder.en...

Android 判断应用是否在前台_外柔内刚的博客-程序员资料

Android 判断应用是否在前台public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.m

3.Junit入门简介 _chaohuis的博客-程序员资料

3.Junit入门简介 3.1、JUnit的好处和JUnit单元测试编写原则 好处: A、可以使测试代码与产品代码分开。 B、针对某一个类的测试代码通过较少的改动便可以应用于另一个类的测试。 C、易于集成到测试人员的构建过程中,JUnit和Ant的结合可以实施增量开发。 D、JUnit是公开源代码的,可以进行二次开发。 C、可以方便地对JUnit进行扩展。 编写原则: A、是简化测试的编写,这种简

ORM框架之GreenDao3.0使用详解(二)_weixin_33727510的博客-程序员资料

本文介绍  上一篇讲解了GreenDao3.0如何集成环境与添加各类注解,这一篇我们来看看如何使用GreenDao实现数据库增删改查的功能,还是上一篇公司Company与雇员Employee的例子。  数据库初始化  首先初始化数据库与表,可封装一个工具类,这里献上我的:public class GreenDaoUtil { private static DaoSession da...

推荐文章

热门文章

相关标签