两个surfaceView实现切换效果

需求:视频通话界面,两个surfaceView一个显示本端的视图,另一个显示对端的视图,由于显示比例的问题总会存在一个覆盖另一个的问题,为保证用户体验,规定小的覆盖大的视图上面,且点击小的视图可切花为大图视图居中,达到两个视图切花的功能。简单写一个demo完成功能的测试需求,为了较少文章的篇幅,视图的内容用回执矩形代替(实际开发中显示的是本地照相采集的数据和对端经过opgl处理的数据)

简单的布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent" >

 <RelativeLayout
 android:id="@+id/remote_rl"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"

  >

 <SurfaceView
  android:id="@+id/remote_view"
  android:layout_width="match_parent"
  android:layout_height="match_parent"

</RelativeLayout> android:layout_gravity="center" />

 </RelativeLayout>

 <RelativeLayout
 android:id="@+id/local_rl"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"

 >

 <SurfaceView
  android:id="@+id/local_view"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content" />
</RelativeLayout>

具体的demo实现

public class MainActivity extends Activity implements View.OnClickListener {
 public static final String TAG = "sssss";
 //远端的视图
 private SurfaceView remote_sv;
 // 本地的视图
 private SurfaceView local_sv;
 private SurfaceHolder remote_holder;
 private SurfaceHolder local_holder;
 private RelativeLayout remote_rl;
 private RelativeLayout local_rl;

 private int screenWidth;
 private int screenHeight;

 private int beforRemoteweith;
 private int beforLocalweith;
 private int beforRemoteheigth;
 private int beforLocalheigth;
 private int StateAB = 0;
 private int StateBA = 1;
 private int mSate;
 private int defaultLocalHeight=200;
 private int defaultLocalwidth=400;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 DisplayMetrics dm = getResources().getDisplayMetrics();
 screenWidth = dm.widthPixels;
 screenHeight = dm.heightPixels - 500;
 remote_sv = (SurfaceView) findViewById(R.id.remote_view);
 remote_rl = (RelativeLayout) findViewById(R.id.remote_rl);
 local_rl = (RelativeLayout) findViewById(R.id.local_rl);
 remote_sv.setOnClickListener(this);

 LayoutParams params = new LayoutParams(screenWidth, screenHeight);
 remote_sv.setLayoutParams(params);
 remote_holder = remote_sv.getHolder();
 // 对 surfaceView 进行操作
 remote_holder.addCallback(new SurfaceHolder.Callback() {
  @Override
  public void surfaceCreated(SurfaceHolder holder) {
  Canvas c = remote_holder.lockCanvas();
  // 2.开画
  Paint p = new Paint();
  p.setColor(Color.RED);
  Rect aa = new Rect(0, 0, holder.getSurfaceFrame().width(),
   holder.getSurfaceFrame().height());
  c.drawRect(aa, p);
  // 3. 解锁画布 更新提交屏幕显示内容
  remote_holder.unlockCanvasAndPost(c);
  }

  @Override
  public void surfaceChanged(SurfaceHolder holder, int format,
   int width, int height) {
  /**
  *
  Log.d(TAG,"remote_holder surfaceChanged width"+ width+"height"+height);
  Canvas c = remote_holder.lockCanvas();
  // 2.开画
  Paint p = new Paint();
  p.setColor(Color.RED);
  Rect aa = new Rect(0, 0, holder.getSurfaceFrame().width(),
   holder.getSurfaceFrame().height());
  c.drawRect(aa, p);
  // 3. 解锁画布 更新提交屏幕显示内容
  remote_holder.unlockCanvasAndPost(c);
  */}

  @Override
  public void surfaceDestroyed(SurfaceHolder holder) {

  }
 });// 自动运行surfaceCreated以及surfaceChanged

 local_sv = (SurfaceView) findViewById(R.id.local_view);
 local_sv.setOnClickListener(this);
 local_sv.setOnClickListener(this);
 // sv.setZOrderOnTop(false);
 local_sv.setZOrderOnTop(true);
 // 这两个方法差不多,设置了就会浮现到顶部,但是,后面的看不见,要像下面设置为透明
 // local_sv.setZOrderOnTop(true);
 // local_sv.setZOrderMediaOverlay(true);

 local_holder = local_sv.getHolder();

 remote_holder.setFormat(PixelFormat.TRANSPARENT);
 local_holder.setFormat(PixelFormat.TRANSPARENT);
 LayoutParams params1 = new LayoutParams(defaultLocalHeight, defaultLocalwidth);
 local_sv.setLayoutParams(params1);
 remote_holder = remote_sv.getHolder();
 local_holder.addCallback(new SurfaceHolder.Callback() {
  @Override
  public void surfaceCreated(SurfaceHolder holder) {
  Canvas c = holder.lockCanvas();
  // 2.开画
  Paint p = new Paint();
  p.setColor(Color.YELLOW);
  Rect aa = new Rect(0, 0, holder.getSurfaceFrame().width(),
   holder.getSurfaceFrame().height());
  c.drawRect(aa, p);
  // 3. 解锁画布 更新提交屏幕显示内容
  holder.unlockCanvasAndPost(c);
  }

  @Override
  public void surfaceChanged(SurfaceHolder holder, int format,
   int width, int height) {
 /**
  *
  Log.d(TAG,"local_holder surfaceChanged width"+ width+"height"+height);
  Canvas c = holder.lockCanvas();
  // 2.开画
  Paint p = new Paint();
  p.setColor(Color.YELLOW);
  Rect aa = new Rect(0, 0, holder.getSurfaceFrame().width()-50,
   holder.getSurfaceFrame().height()-50);
  c.drawRect(aa, p);
  // 3. 解锁画布 更新提交屏幕显示内容
  holder.unlockCanvasAndPost(c);

  */}

  @Override
  public void surfaceDestroyed(SurfaceHolder holder) {

  }
 });
 zoomOpera(local_rl, local_sv, remote_sv, remote_rl, defaultLocalwidth,
  defaultLocalHeight, RelativeLayout.CENTER_IN_PARENT);
 }

 @Override
 public void onClick(View view) {
 switch (view.getId()) {
 case R.id.local_view:
  Log.d(TAG, " onClick local_view" + mSate);
  if (mSate == StateAB) {
  zoomlocalViewout(beforRemoteweith, beforRemoteheigth, local_sv,
   remote_sv);
  zoomRemoteViewint(beforLocalweith, beforLocalheigth);
  mSate = StateBA;
  }

  break;
 case R.id.remote_view:
  Log.d(TAG, " onClick emote_view" + mSate);
  if (mSate == StateBA) {

  zoomRemoteout(beforRemoteweith, beforRemoteheigth, local_sv,
   remote_sv);
  zoomlocalViewint(beforLocalweith, beforLocalheigth);

  mSate = StateAB;
  }

  break;
 default:
  break;
 }

 }
//放大远端的视图
 private void zoomRemoteout(int weith2, int heigth2, SurfaceView localView,
  SurfaceView remoteView) {

 beforLocalheigth = localView.getMeasuredHeight();
 beforLocalweith = localView.getMeasuredWidth();
 beforRemoteheigth = remoteView.getMeasuredHeight();
 beforRemoteweith = remoteView.getMeasuredWidth();
 Log.d(TAG, "zoomRemoteout beforLocalheigth" + beforLocalheigth
  + "beforLocalweith" + beforLocalweith + "beforRemoteheigth"
  + beforRemoteheigth + "beforRemoteweith" + beforLocalweith);
 zoomOpera(local_rl, local_sv, remote_sv, remote_rl, screenWidth,
  beforLocalheigth, RelativeLayout.CENTER_IN_PARENT);

 }
//具体的视图操作
 private void zoomOpera(View sourcView, SurfaceView beforeview,
  SurfaceView afterview, View detView, int beforLocalweith,
  int beforLocalHeigth, int rule) {

 LayoutParams params1 = new LayoutParams(LayoutParams.MATCH_PARENT,
  LayoutParams.MATCH_PARENT);

 Log.w(TAG, "beforLocalheigth = " + beforLocalheigth
  + "; beforLocalweith = " + beforLocalweith);
 params1.addRule(rule, RelativeLayout.TRUE);
 afterview.setLayoutParams(params1);
 afterview.setBackgroundResource(android.R.color.transparent);
 params1 = new LayoutParams(beforLocalweith, beforLocalHeigth);
 params1.addRule(rule, RelativeLayout.TRUE);
 detView.setLayoutParams(params1);

 }
//缩小远端的视图
 private void zoomRemoteViewint(int weith2, int heigth2) {
 RelativeLayout paretview = (RelativeLayout) local_rl.getParent();
 paretview.removeView(remote_rl);
 paretview.removeView(local_rl);
 zoomOpera(local_rl, local_sv, remote_sv, remote_rl, beforLocalweith,
  beforLocalheigth, RelativeLayout.ALIGN_PARENT_TOP);
 Log.d(TAG, "paretview" + paretview.getChildCount());
 paretview.addView(local_rl);
 paretview.addView(remote_rl);
 remote_sv.setZOrderOnTop(true);

 }
//放大本端的视图
 private void zoomlocalViewout(int weith2, int heigth2,
  SurfaceView localView, SurfaceView remoteView) {
 beforLocalheigth = localView.getMeasuredHeight();
 beforLocalweith = localView.getMeasuredWidth();
 beforRemoteheigth = remoteView.getMeasuredHeight();
 beforRemoteweith = remoteView.getMeasuredWidth();
 Log.d(TAG, "zoomlocalViewout beforLocalheigth" + beforLocalheigth
  + "beforLocalweith" + beforLocalweith + "beforRemoteheigth"
  + beforRemoteheigth + "beforRemoteweith" + beforRemoteweith);
 zoomOpera(remote_rl, remote_sv, local_sv, local_rl, beforRemoteweith,
  beforRemoteheigth, RelativeLayout.CENTER_IN_PARENT);

 }
//减小本端的视图
 private void zoomlocalViewint(int weith2, int heigth2) {
 RelativeLayout paretview = (RelativeLayout) local_rl.getParent();
 paretview.removeView(remote_rl);
 paretview.removeView(local_rl);
 zoomOpera(remote_rl, remote_sv, local_sv, local_rl, beforRemoteweith,
  beforRemoteheigth, RelativeLayout.ALIGN_PARENT_TOP);
 paretview.addView(remote_rl);
 paretview.addView(local_rl);
 local_sv.setZOrderOnTop(true);

 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android切换至SurfaceView时闪屏(黑屏闪一下)以及黑屏移动问题的解决方法

    1.最近的项目中,有一个Activity用到Fragment+ViewPager,其中一个fragment中实现了视频播放的功能,包含有SurfaceView.结果,每次打开程序第一次进入到该Activity时都会闪屏黑一下.原因就出在SurfaceView. 详解: I think I found the reason for the black flash. In my case I'm using a SurfaceView inside a Fragment and dynamicall

  • Android SurfaceView运行机制剖析--处理切换到后台再重新进入程序时的异常

    有不少朋友都遇到过这种问题,程序执行时切换到后台,然后再重新进入会报异常,本文就这种问题全面讲解下SurfaceView的运行机制,了解了这些原理你就能自己解决这些问题了. 我们通常会通过单击HOME按键或返回按键等操作切换到后台,之后可能会再次进入程序,这个时候就有可能报异常.这里SurfaceView可能报的异常主要有两点,如下: 一.提交画布异常.如下图(模拟器错误提示,以及Logcat Detail) Java代码 public void draw() { try { canvas =

  • Android Fragment中使用SurfaceView切换时闪一下黑屏的解决办法

    重构了下之前自己的一个新闻客户端,全部使用了Fragment来进行页面切换,只有一个入口Activity作为程序的启动Activity,其中有一个界面需要调用摄像头识别二维码,于是就会用到SurfaceView进行预览,那么问题来了,当切换到对应的Fragment时,屏幕会黑一下,黑了1秒左右就显示出正常的界面,而且这种现象只有第一次进入该Fragment才会出现,之后进入都不会出现,解决方法是无意在github上看到了,试了一下,可以行的通,下面贴出解决方法. 方法一.在Activity的on

  • 两个surfaceView实现切换效果

    需求:视频通话界面,两个surfaceView一个显示本端的视图,另一个显示对端的视图,由于显示比例的问题总会存在一个覆盖另一个的问题,为保证用户体验,规定小的覆盖大的视图上面,且点击小的视图可切花为大图视图居中,达到两个视图切花的功能.简单写一个demo完成功能的测试需求,为了较少文章的篇幅,视图的内容用回执矩形代替(实际开发中显示的是本地照相采集的数据和对端经过opgl处理的数据) 简单的布局 <?xml version="1.0" encoding="utf-8&

  • jquery实现两个图片渐变切换效果的方法

    本文实例讲述了jquery实现两个图片渐变切换效果的方法.分享给大家供大家参考.具体如下: 这段代码演示了jquery如何实现两个图片渐变切换的效果,为id=kitten的div设置一个背景图片,通过jquery对div进行淡入淡出实现两个图片的渐变切换 html代码 <div id="kitten"> <img src="/images/kitten.jpg" alt="Kitten" /> </div> j

  • 基于jquery实现左右按钮点击的图片切换效果

    jQuery可以制作出与Flash媲美的动画效果,这点绝对毋庸置疑,本文将通过实例演示一个左右按钮点击的图片切换效果. 一.最终效果 二.功能分析 1.需求分析 点击左边pre按钮,显示前面三个图片,点击右边的next按钮,显示后面的一组(三个)图片.初始化只显示next按钮,到最后一组只显示pre按钮,中间过程两按钮都显示. 2.html结构分析 <div class="activity" id="activity-slide"> <a href

  • JS封装的选项卡TAB切换效果示例

    本文实例讲述了JS封装的选项卡TAB切换效果.分享给大家供大家参考,具体如下: <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8"> <title>JS封装的选项卡TAB代码</title> <style type="text/css"> *{ padding:0; margin:0;}

  • js中常用的Tab切换效果(推荐)

    如下所示: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>tab</title> <style> *{margin:0; padding:0; list-style:none;} .box{ width: 1000px; overflow: hidden; margin:100px auto

  • 纯js无flash仿搜狐女人频道FLASH图片切换效果代码

    前2个星期看到一位朋友说如何用JS实现http://women.sohu.com/这个页中FLASH图片切换效果,这两天有空,做了一个,大家评评: [加载图片慢点请等会] www.jb51.net 我们 JS图片切换 :: * { margin:0; padding:0; } body { margin:0; color:#88c; background:#333; } img { margin:0; padding:0; border:0; } #js_F { position:relativ

  • Android自定义ViewPager实现个性化的图片切换效果

    第一次见到ViewPager这个控件,瞬间爱不释手,做东西的主界面通通ViewPager,以及图片切换也抛弃了ImageSwitch之类的,开始让ViewPager来做.时间长了,ViewPager的切换效果觉得枯燥,形成了审美疲劳~~我们需要改变,今天教大家如何改变ViewPager切换时的效果,实现个性化的图片切换 看一下这样效果的图片切换: 是不是比传统的效果个性很多,嘿嘿~~其实很简单,学习完这篇文章,保证你可以自定义切换效果,做出各式各样的效果. 1.制作前的分析 观察下效果图,实际上

  • js+div实现文字滚动和图片切换效果代码

    本文实例讲述了js+div实现文字滚动和图片切换效果代码.分享给大家供大家参考.具体如下: 这里演示js+div文字滚动和图片切换代码,为了演示方便,去掉了图片调用,用数字代替了,用时候再加上就可以了,本效果实现了两种效果,Div切换,TAB切换,和文字滚动,鼠标移上后文字停止滚动,两种功能可任意剥离出来,这不影响代码使用. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-div-txt-pic-scroll-cha-style-codes

  • 实用的js 焦点图切换效果 结构行为相分离

    焦点图切换效果,对前端来说,恐怕再熟悉不过了,实现它的方法应该有多种,工作当中常用的一种,叙述如下: 如何让当前的数字导航与图片的显示同步? 这里有两个区域,图片切换区和数字导航区:分别对应着两个循环函数:plays(value)和setBg(value): 当图片循环切换到第2张时,此时数字导航的当前状态也变换到第2的位置,以此达到一种同步的效果,这里的关键就是给他们传递相同的参数value:而这个任务就交给了函数Mea(value): 图片应该是自动切换的,当循环显示到最后一种图片后,返回到

  • 很棒的js Tab选项卡切换效果

    本文实例为大家分享了js Tab选项卡切换效果,供大家参考,具体内容如下 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>tab</title> <style> *{margin:0; padding:0; list-style:none;} .box{ width: 1000px; over

随机推荐