android surfaceview学习(一)

article/2025/11/3 15:15:30

推荐阅读:
https://blog.csdn.net/luoshengyang/article/details/8661317
https://www.cnblogs.com/xuling/archive/2011/06/06/android.html
https://blog.csdn.net/zcmain/article/details/14454953

1、surfaceview默认是黑色的背景,并且给sfv设置背景颜色会覆盖在播放的画面上
在这里插入图片描述
2、上下层surfaceview,当下层sfv开始播放画面,上层sfv自动会变为透明
在这里插入图片描述
3、当上层surfaceview gone之后,父布局设置的背景色才会生效
在这里插入图片描述
4、一旦sfv gone,就会回调surfaceDestroyed,surface先销毁,之后sfv被隐藏,重新显示时候,需要再次在surfaceCreated回调中绑定
mediaPlayer2.setDisplay(holder);
否则sfv会没有画面,好像被挖空,显示下层画面
在这里插入图片描述
5、当下层、上层surfaceview都在播放视频,上层sfv 的父布局 gone了,会发现上层surfaceview依旧显示,无法隐藏掉。
要想讲sfv隐藏,需要同时
父布局 gone
sfv gone
在这里插入图片描述
6、延迟问题:
surfaceview变得可见时,surface才会被创建,导致:
会出现surfaceview先透明,后出现画面;

surfaceview隐藏之前,surface先被销毁,导致:
透明之后,才会被隐藏。

7、下层surfaceview已经在播放画面,上层sfv会变成透明的(sfv背景颜色生效,所有的父布局颜色均无效),一旦上层sfv mediaplay播放准备耗时,透明时间就会变长。比如;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mediaPlayer2.start();
}
}, 1000);
在这里插入图片描述
还有很多情况,大家可以自行测试,手机上最后使用
String uri = “android.resource://” + getPackageName() + “/” + R.raw.b;
mediaPlayer1.setDataSource(this, Uri.parse(uri));//设置要播放的内容在根目录下的位置
sd卡读取容易出现异常。

package com.example.myapplication.videoplayer;import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Gravity;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;import com.example.myapplication.R;public class VideoPlayActivity2 extends AppCompatActivity implements View.OnClickListener {Button start, pause, stop;MediaPlayer mediaPlayer2;SurfaceHolder surfaceHolder2;Button start1, hidesfv, showsfv, change;SurfaceView sfv1, sfv2;TextView info;FrameLayout sfvfmlayout;FrameLayout sfv2fmlayout;SurfaceHolder surfaceHolder1;MediaPlayer mediaPlayer1 = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_video_play2);int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);if (permission != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 0);}start1 = findViewById(R.id.start1);start1.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {playVideo1();}});info = findViewById(R.id.info);start = findViewById(R.id.start);start.setOnClickListener(this);change = findViewById(R.id.change);change.setOnClickListener(this);pause = findViewById(R.id.pause);pause.setOnClickListener(this);stop = findViewById(R.id.stop);stop.setOnClickListener(this);sfvfmlayout = findViewById(R.id.flsfv1);sfv2fmlayout = findViewById(R.id.flsfv2);sfv1 = findViewById(R.id.sfv1);sfv2 = findViewById(R.id.sfv2);showsfv = findViewById(R.id.show);hidesfv = findViewById(R.id.hide);hidesfv.setOnClickListener(this);showsfv.setOnClickListener(this);isstop = true;//初始化,处于停止播放中//大屏幕surfaceHolder1 = sfv1.getHolder();surfaceHolder1.addCallback(new SurfaceHolder.Callback() {@Overridepublic void surfaceCreated(SurfaceHolder holder) {Log.d(TAG, "surfaceHolder1 surfaceCreated");
//                new Handler().postDelayed(new Runnable() {
//                    @Override
//                    public void run() {playVideo1();
//                    }
//                }, 5000);}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {Log.d(TAG, "surfaceHolder1 surfaceChanged");}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {Log.d(TAG, "surfaceHolder1 surfaceDestroyed");}});//小屏幕surfaceHolder2 = sfv2.getHolder();surfaceHolder2.addCallback(new SurfaceHolder.Callback() {@Overridepublic void surfaceCreated(SurfaceHolder holder) {Log.d(TAG, "surfaceHolder2 surfaceCreated holder=" + holder);playVideo2();}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {Log.d(TAG, "surfaceHolder2 surfaceChanged holder=" + holder);}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {Log.d(TAG, "surfaceHolder2 surfaceDestroyed holder=" + holder);}});}void playVideo2() {//小屏幕mediaPlayer2 = new MediaPlayer();isstop = false;mediaPlayer2.setAudioStreamType(AudioManager.STREAM_MUSIC);mediaPlayer2.reset();//重置MediaPlayermediaPlayer2.setDisplay(surfaceHolder2);//把视频画面输出到SurfaceView中try {//获取raw.mp4的uri地址String uri = "android.resource://" + getPackageName() + "/" + R.raw.a;mediaPlayer2.setDataSource(this, Uri.parse(uri));//设置要播放的内容在根目录下的位置mediaPlayer2.prepare();//预加载info.setText("播放中");} catch (Exception e) {e.printStackTrace();}mediaPlayer2.start();}void playVideo1() {//大屏幕mediaPlayer1 = new MediaPlayer();mediaPlayer1.setAudioStreamType(AudioManager.STREAM_MUSIC);mediaPlayer1.reset();//重置MediaPlayermediaPlayer1.setDisplay(surfaceHolder1);//把视频画面输出到SurfaceView中try {//获取raw.mp4的uri地址String uri = "android.resource://" + getPackageName() + "/" + R.raw.b;mediaPlayer1.setDataSource(this, Uri.parse(uri));//设置要播放的内容在根目录下的位置mediaPlayer1.prepare();//预加载} catch (Exception e) {e.printStackTrace();}
//        new Handler().postDelayed(new Runnable() {
//            @Override
//            public void run() {mediaPlayer1.start();
//            }
//        }, 1000);}boolean ispause = false;boolean isstop = true;String TAG = "lihui";@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.hide:sfv2fmlayout.setVisibility(View.GONE);sfv2.setVisibility(View.GONE);//GONE、INVISIBLE 父布局背景才有效果
//                if (mediaPlayer2 != null) {
//                    try {
//                        mediaPlayer2.pause();
//                        mediaPlayer2.stop();
//                        mediaPlayer2.release();
//                        isstop = true;
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                    }
//                }break;case R.id.show:sfv2fmlayout.setVisibility(View.VISIBLE);
//                sfv2.postDelayed(new Runnable() {
//                    @Override
//                    public void run() {sfv2.setVisibility(View.VISIBLE);
//                    }
//                }, 3000);break;case R.id.start:Log.d(TAG, "1 isstop=" + isstop + ",ispause=" + ispause);if (isstop) {playVideo2();isstop = false;} else if (ispause) {mediaPlayer2.start();ispause = false;}info.setText("播放中");break;case R.id.pause:Log.d(TAG, "2 isstop=" + isstop + ",ispause=" + ispause);if (mediaPlayer2 == null || isstop) return;if (mediaPlayer2.isPlaying()) {mediaPlayer2.pause();ispause = true;info.setText("已暂停");}break;case R.id.stop:Log.d(TAG, "3 isstop=" + isstop + ",ispause=" + ispause);if (mediaPlayer2 == null || isstop) return;mediaPlayer2.stop();mediaPlayer2.release();info.setText("已停止");isstop = true;break;case R.id.change:ViewGroup.LayoutParams layoutParams1 = sfvfmlayout.getLayoutParams();ViewGroup.LayoutParams layoutParams2 = sfv2fmlayout.getLayoutParams();sfvfmlayout.setLayoutParams(layoutParams2);sfv2fmlayout.setLayoutParams(layoutParams1);sfv2.setZOrderMediaOverlay(true);sfv1.setZOrderMediaOverlay(true);if (sfvfmlayout.getLayoutParams().width == ViewGroup.LayoutParams.MATCH_PARENT) {sfv2fmlayout.bringToFront();//sfv2小屏幕stop2();playVideo2();//sfv2.setVisibility(View.VISIBLE);Log.d(TAG, "playVideo2");} else {sfvfmlayout.bringToFront();//sfv1小屏幕stop1();playVideo1();//  sfv1.setVisibility(View.VISIBLE);Log.d(TAG, "playVideo1");}break;}}void stop1() {try {if (mediaPlayer1 != null) {mediaPlayer1.stop();mediaPlayer1.release();Log.d(TAG, "stop1");}} catch (Exception e) {}}void stop2() {try {if (mediaPlayer2 != null) {mediaPlayer2.stop();mediaPlayer2.release();Log.d(TAG, "stop2");}} catch (Exception e) {}}@Overrideprotected void onDestroy() {super.onDestroy();stop1();stop2();}
}
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".videoplayer.VideoPlayActivity"><FrameLayoutandroid:id="@+id/parent"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><FrameLayoutandroid:id="@+id/flsfv1"android:layout_width="match_parent"android:layout_height="250dp"><SurfaceViewandroid:id="@+id/sfv1"android:layout_width="match_parent"android:layout_height="match_parent"android:visibility="visible" /><TextViewandroid:layout_width="wrap_content"android:layout_height="30dp"android:layout_gravity="bottom"android:text="主画面"android:textColor="#ff5500"android:textSize="20dp" /></FrameLayout><FrameLayoutandroid:id="@+id/flsfv2"android:layout_width="100dp"android:layout_height="150dp"android:layout_gravity="bottom|right"android:visibility="visible"><SurfaceViewandroid:id="@+id/sfv2"android:layout_width="match_parent"android:layout_height="match_parent" /><TextViewandroid:id="@+id/info"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="bottom"android:text="停止"android:textColor="#ff5500"android:textSize="20dp" /></FrameLayout></FrameLayout><Buttonandroid:id="@+id/start1"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="surfaceview1播放" /><Buttonandroid:id="@+id/start"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="surfaceview2播放" /><Buttonandroid:id="@+id/pause"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="surfaceview2暂停" /><Buttonandroid:id="@+id/stop"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="surfaceview2停止" /><Buttonandroid:id="@+id/hide"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="surfaceview2隐藏" /><Buttonandroid:id="@+id/show"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="surfaceview2显示" /><Buttonandroid:id="@+id/change"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="交换surfaceview1、2位置" /></LinearLayout>
</ScrollView>

http://chatgpt.dhexx.cn/article/1SbF9KJA.shtml

相关文章

Activity、Fragment和Surface的生命周期

这里首先推荐大家一本Android的学习书籍&#xff1a;《第一行代码》&#xff0c;这本书还是写得非常好的。好了&#xff0c;进入正题&#xff0c;我们先来了解一下Activity、Fragment的的生命周期中经历的几个阶段。 ActivityFragment 下面我们假设有如下的场景&#xff0c;Act…

Java进度条

转自&#xff1a;点击打开链接 进度条用在很多的地方&#xff0c;比如登录验证等待过程、程序加载、数据下载、数据更新与删除等&#xff0c;它可以一目了然的让用户知道程序执行的进度。下面给大家看一个登录验证的进度条&#xff0c;首先上效果图&#xff1a; 在代码中未连接…

java窗口进度条_java进度条窗口具体如何制作?

可视化窗口是大部分游戏的常态&#xff0c;今天我们就来了解下如何编写进度条窗口&#xff0c;快跟小编一起看看吧。 一、在包右击new->other->WindowBuilder->JFrame->name叫Guithreadpackage guithread; import java.awt.BorderLayout; import java.awt.EventQue…

java进度条_「java进度条」Java JProgressBar类(进度条) - seo实验室

java进度条 简介 利用JprogressBar类可以实现一个进度条。它一般是一种颜色部分或完全填充的矩形。缺省情况下,进度条配备了一个凹陷的边框,并水平放置。 进度条还可以选择显示一个字符串,这个字符串在进度条矩形的中央位置上显示。这个字符串缺省时为耗时任务已完成的百分比…

Java 进度条

效果 代码 思路&#xff1a;使用NumberFormat类来格式化数字&#xff0c;显示完后&#xff0c;退格覆盖重新显示新的数字 import java.text.NumberFormat;public class Test {public static void main(String[] args) throws Exception {System.out.print("Progress:"…

Java图形化界面---进度条

目录 一、进度条的介绍 二、创建进度条 三、简单案例 四、子线程创建进度条 &#xff08;1&#xff09;为什么要使用子线程创建进度条 &#xff08;2&#xff09;子线程创建进度条的代码 五、创建进度对话框 &#xff08;1&#xff09;如何创建进度对话框 &#xff08;2&…

Java图形化界面编程超详细知识点(7)——进度条

目录 4 JProgressBar、ProgressMonitor、BoundedRangeModel实现进度条 4.1 创建进度条 4 JProgressBar、ProgressMonitor、BoundedRangeModel实现进度条 进度条是图形界面中广泛使用的GUI组件&#xff0c;当复制一个较大的文件时&#xff0c;操作系统会显示一个进度条&#…

Java制作进度条

【效果图】 【描述】 进度条宽度保持和窗口宽度一致&#xff0c;进度最小值为0&#xff0c;最大值为100&#xff0c;每100毫秒进度值1&#xff0c;进度条中间显示进度百分比 【代码】 package test;import java.awt.*; import java.awt.event.*;import javax.swing.*;public…

QT:QGraphicsScene与QGraphicsView使用render()函数渲染图片

render()函数看官方文档&#xff0c;会有很多不懂得地方&#xff0c;以下为实践出来的效果。 当我们想要用QPaint() 绘制我们在QGraphicsView看到的部分时&#xff0c;不仅要绘制正确的图片大小&#xff0c;还需要使用 render() 渲染正确的大小。当我们只想要绘制坐标系中矩形…

Qt图形特效:QGraphicsOpacityEffect

一、描述 不透明度效果使源具有不透明度。该效果对于使源半透明非常有用&#xff0c;类似于淡入/淡出序列。可以使用setOpacity()函数修改不透明度。 二、属性成员 1、opacity : qreal。此属性保存不透明度。该值应在0.0到1.0的范围内&#xff0c;其中0.0是完全透明的&#…

图形视图(02):【类】QGraphicsScene [官翻]

文章目录 详述事件处理和传播 公共类型enum ItemIndexMethodenum SceneLayer 属性backgroundBrush: QBrushbspTreeDepth: intfocusOnTouch: boolfont: QFontforegroundBrush: QBrushitemIndexMethod: ItemIndexMethodminimumRenderSize: qrealpalette: QPalette**sceneRect**: …

Qt中使用QGraphicsScene重写drawBackGround绘制背景

Qt中使用QGraphicsScene重写drawBackGround绘制背景 需求解释 我是想这学习Qt的界面设计&#xff0c;希望能够对界面背景进行优化然后使用Qt的界面与图形画背景网格。首先查资料 通过查找博客发现很简单&#xff0c;就是新建一个类继承于QGraphicsScene&#xff0c;于是我就…

图形视图框架QGraphicsScene(场景,概念)

QGraphicsScene 该类充当 QGraphicsItems 的容器。它与 QGraphicsView 一起使用&#xff0c;用于在 2D 表面上可视化图形项目&#xff0c;例如线条、矩形、文本甚至自定义项目。 QGraphicsScene具有的功能&#xff1a; 提供用管理大量数据项的高速接口传播事件到每一个图形项…

qt学习笔记(五) QGraphicsPixmapItem与QGraphicsScene的编程实例 图标拖动渐变效果

应大家的要求&#xff0c;还是把完整的工程文件贴出来&#xff0c;大家省点事&#xff1a;http://www.kuaipan.cn/file/id_48923272389086450.htm 先看看运行效果&#xff0c;我用的群创7寸屏&#xff0c;主机是mini2440&#xff0c;分辨率是800*480&#xff0c;程序写比较粗糙…

Qt QGraphicsScene、QGraphicsView类实现仪表盘

Qt QGraphicsScene、QGraphicsView类实现仪表盘 【1】UI界面设计【2】效果【3】QGraphicsScene简介【4】QGraphicsEllipseItem简介【5】QGraphicsPolygonItem简介【6】QGraphicsLineItem简介【7】QGraphicsView简介【8】仪表源码头文件源码 【1】UI界面设计 【2】效果 【3】QGr…

qt QGraphicsScene 简单例子

坐标 graphicsView是Widget这个界面的子控件&#xff0c; 他的位置是左上角坐标为&#xff08;30,30&#xff09; 他的宽度为431&#xff0c;高度为431. 如果在graphicsView 这个子控件中&#xff0c; 继续加入 子控件A&#xff0c;由于graphicsView比较特殊。 根据它的align…

QGraphicsScene设置SceneRect

简要说明 QGraphicsScene场景区域&#xff0c;可在构造QGraphicsScene对象时设定&#xff0c;也可通过函数setSceneRect设定。QGraphicsScene场景区域中坐标原点的位置&#xff0c;会影响到图形项的坐标设定&#xff0c;进而影响图形项在场景中的显示位置。以将图片显示在中心…

QT QGraphicsScene / QGraphicsView中 sceneRect 使用详细说明

接触QT不久&#xff0c;发现QT的Graphics View框架坐标使用和平常不一样&#xff0c;尤其sceneRect的作用。 官方文档关于这部分介绍真是蛋疼&#xff0c;网上说的也寥寥。没法自己研究了一下&#xff0c;其实这块内容QT设计的很方便&#xff0c;只是文档讲解的太烂&#xff0c…

【QT】GraphicsView、QGraphicsScene、QGraphicsEllipseItem的使用

GraphicsView、QGraphicsScene、QGraphicsEllipseItem的使用 前言实验目的重构GraphicsView类新建GraphicsView、QGraphicsScene层绘制Item图形控件绘制圆形绘制矩形绘制三角形绘制文字绘制直线 组合、打散、前置和后置组合打散控件前置控件后置 绑定功能事件总结 前言 对于绘…

Qt 绘图之QGraphicsScene QGraphicsView QGraphicsItem详解

Graphics View提供了一个界面&#xff0c;它既可以管理大数量的定制2D graphical items&#xff0c;又可与它们交互&#xff0c;有一个view widget可以把这些项绘制出来&#xff0c;并支持旋转与缩放。这个柜架也包含一个事件传播结构&#xff0c;对于在scene中的这些items,它具…