基于SurfaceView实现可拖动视频控件

本文实例为大家分享了基于SurfaceView的可拖动视频控件,供大家参考,具体内容如下

public class DragSurfaceView extends SurfaceView implements View.OnTouchListener {
  protected int screenWidth;
  protected int screenHeight;
  protected int lastX;
  protected int lastY;
  private int oriLeft;
  private int oriRight;
  private int oriTop;
  private int oriBottom;
  private int dragDirection;
  private static final int TOP = 0x15;
  private static final int LEFT = 0x16;
  private static final int BOTTOM = 0x17;
  private static final int RIGHT = 0x18;
  private static final int LEFT_TOP = 0x11;
  private static final int RIGHT_TOP = 0x12;
  private static final int LEFT_BOTTOM = 0x13;
  private static final int RIGHT_BOTTOM = 0x14;
  private static final int CENTER = 0x19;
  private int offset = 20;

  /**
   * 初始化获取屏幕宽高
   */
  protected void initScreenW_H() {
    screenHeight = getResources().getDisplayMetrics().heightPixels - 40;
    screenWidth = getResources().getDisplayMetrics().widthPixels;
    Log.i("DragViewTAG", "DragSurfaceView.initScreenW_H: screenWidth="+screenWidth+", screenHeight="+screenHeight);
  }
  public DragSurfaceView(Context context) {
    super(context);
    setOnTouchListener(this);
    initScreenW_H();
  }

  public DragSurfaceView(Context context, AttributeSet attrs) {
    super(context, attrs);
    setOnTouchListener(this);
    initScreenW_H();
  }

  public DragSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    setOnTouchListener(this);
    initScreenW_H();
  }

  @Override
  public boolean onTouch(View v, MotionEvent event) {
    int action = event.getAction();
    if (action == MotionEvent.ACTION_DOWN) {
      oriLeft = v.getLeft();
      oriRight = v.getRight();
      oriTop = v.getTop();
      oriBottom = v.getBottom();
      lastY = (int) event.getRawY();
      lastX = (int) event.getRawX();
      dragDirection = getDirection(v, (int) event.getX(),
          (int) event.getY());
    }
    // 处理拖动事件
    delDrag(v, event, action);
    if(action==MotionEvent.ACTION_UP){
      dragDirection=0;
    }
    invalidate();
    return true;
  }

  /**
   * 获取触摸点flag
   *
   * @param v
   * @param x
   * @param y
   * @return
   */
  protected int getDirection(View v, int x, int y) {
    int left = v.getLeft();
    int right = v.getRight();
    int bottom = v.getBottom();
    int top = v.getTop();
    if (x < 40 && y < 40) {
      return LEFT_TOP;
    }
    if (y < 40 && right - left - x < 40) {
      return RIGHT_TOP;
    }
    if (x < 40 && bottom - top - y < 40) {
      return LEFT_BOTTOM;
    }
    if (right - left - x < 40 && bottom - top - y < 40) {
      return RIGHT_BOTTOM;
    }
    if (x < 40) {
      return LEFT;
    }
    if (y < 40) {
      return TOP;
    }
    if (right - left - x < 40) {
      return RIGHT;
    }
    if (bottom - top - y < 40) {
      return BOTTOM;
    }
    return CENTER;
  }

  /**
   * 处理拖动事件
   *
   * @param v
   * @param event
   * @param action
   */
  protected void delDrag(View v, MotionEvent event, int action) {
    switch (action) {
      case MotionEvent.ACTION_MOVE:
        int dx = (int) event.getRawX() - lastX;
        int dy = (int) event.getRawY() - lastY;
        switch (dragDirection) {
          case LEFT: // 左边缘
            left(v, dx);
            break;
          case RIGHT: // 右边缘
            right(v, dx);
            break;
          case BOTTOM: // 下边缘
            bottom(v, dy);
            break;
          case TOP: // 上边缘
            top(v, dy);
            break;
          case CENTER: // 点击中心-->>移动
            center(v, dx, dy);
            break;
          case LEFT_BOTTOM: // 左下
            left(v, dx);
            bottom(v, dy);
            break;
          case LEFT_TOP: // 左上
            left(v, dx);
            top(v, dy);
            break;
          case RIGHT_BOTTOM: // 右下
            right(v, dx);
            bottom(v, dy);
            break;
          case RIGHT_TOP: // 右上
            right(v, dx);
            top(v, dy);
            break;
          default:
            break;
        }
        v.layout(oriLeft, oriTop, oriRight, oriBottom);
//        if (dragDirection != CENTER) {
//          v.layout(oriLeft, oriTop, oriRight, oriBottom);
//        }
        lastX = (int) event.getRawX();
        lastY = (int) event.getRawY();
        Log.i("DragViewTAG", "DragSurfaceView.delDrag:ACTION_MOVE direction="+dragDirection+", left="+oriLeft+", top="+oriTop+", right="+oriRight+", bottom="+oriBottom);
        break;
      case MotionEvent.ACTION_UP:
        ViewGroup.LayoutParams newLayoutParams = getNewLayoutParams();
        if(newLayoutParams!=null){
          Log.i("DragViewTAG", "DragSurfaceView.delDrag:ACTION_UP width="+newLayoutParams.width+", height="+newLayoutParams.height);
          setLayoutParams(newLayoutParams);
        }else {
          Log.e("DragViewTAG", "DragSurfaceView.delDrag: 父组件类型?");
          v.layout(oriLeft, oriTop, oriRight, oriBottom);
        }
        break;
      default:
        break;
    }
  }

  private ViewGroup.LayoutParams getNewLayoutParams(){
    if(getLayoutParams() instanceof RelativeLayout.LayoutParams){
      RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)getLayoutParams( );
      lp.leftMargin = oriLeft;
      lp.topMargin = oriTop;
      lp.width = oriRight-oriLeft;
      lp.height = oriBottom-oriTop;
      return lp;
    }else if(getLayoutParams() instanceof FrameLayout.LayoutParams) {
      FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
      lp.leftMargin = oriLeft;
      lp.topMargin = oriTop;
      lp.width = oriRight - oriLeft;
      lp.height = oriBottom - oriTop;
      return lp;
    }
    return null;
  }

  /**
   * 触摸点为中心->>移动
   *
   * @param v
   * @param dx
   * @param dy
   */
  private void center(View v, int dx, int dy) {
    oriLeft += dx;
    oriTop += dy;
    oriRight += dx;
    oriBottom += dy;
    Log.i("DragViewTAG", "DragSurfaceView.center: v.left="+v.getLeft()+", v.top="+v.getTop());
    if (oriLeft < -offset) {
      Log.e("DragViewTAG", "DragSurfaceView.center: 左侧越界, left="+oriLeft+", offset="+offset);
      oriLeft = -offset;
      oriRight = oriLeft + v.getWidth();
    }
    if (oriRight > screenWidth + offset) {
      Log.e("DragViewTAG", "DragSurfaceView.center: 右侧越界, right="+oriRight+", screenWidth="+screenWidth+", offset="+offset);
      oriRight = screenWidth + offset;
      oriLeft = oriRight - v.getWidth();
    }
    if (oriTop < -offset) {
      Log.e("DragViewTAG", "DragSurfaceView.center: 顶部越界, top="+oriTop+", offset="+offset);
      oriTop = -offset;
      oriBottom = oriTop + v.getHeight();
    }
    if (oriBottom > screenHeight + offset) {
      Log.e("DragViewTAG", "DragSurfaceView.center: 底部越界, bottom="+oriBottom+", screenHeight="+screenHeight+", offset="+offset);
      oriBottom = screenHeight + offset;
      oriTop = oriBottom - v.getHeight();
    }
//    v.layout(left, top, right, bottom);

  }

  /**
   * 触摸点为上边缘
   *
   * @param v
   * @param dy
   */
  private void top(View v, int dy) {
    oriTop += dy;
    if (oriTop < -offset) {
      oriTop = -offset;
    }
    if (oriBottom - oriTop - 2 * offset < 200) {
      oriTop = oriBottom - 2 * offset - 200;
    }
  }

  /**
   * 触摸点为下边缘
   *
   * @param v
   * @param dy
   */
  private void bottom(View v, int dy) {
    oriBottom += dy;
    if (oriBottom > screenHeight + offset) {
      oriBottom = screenHeight + offset;
    }
    if (oriBottom - oriTop - 2 * offset < 200) {
      oriBottom = 200 + oriTop + 2 * offset;
    }
  }

  /**
   * 触摸点为右边缘
   *
   * @param v
   * @param dx
   */
  private void right(View v, int dx) {
    oriRight += dx;
    if (oriRight > screenWidth + offset) {
      oriRight = screenWidth + offset;
    }
    if (oriRight - oriLeft - 2 * offset < 200) {
      oriRight = oriLeft + 2 * offset + 200;
    }
  }

  /**
   * 触摸点为左边缘
   *
   * @param v
   * @param dx
   */
  private void left(View v, int dx) {
    oriLeft += dx;
    if (oriLeft < -offset) {
      oriLeft = -offset;
    }
    if (oriRight - oriLeft - 2 * offset < 200) {
      oriLeft = oriRight - 2 * offset - 200;
    }
  }

  /**
   * 获取截取宽度
   *
   * @return
   */
  public int getCutWidth() {
    return getWidth() - 2 * offset;
  }

  /**
   * 获取截取高度
   *
   * @return
   */
  public int getCutHeight() {
    return getHeight() - 2 * offset;
  }
}

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

(0)

相关推荐

  • android图像绘制(四)自定义一个SurfaceView控件

    自定义控件(类似按钮等)的使用,自定义一个SurfaceView. 如某一块的动态图(自定义相应),或者类似UC浏览器下面的工具栏. 如下图示例:  自定义类代码: 复制代码 代码如下: public class ImageSurfaceView extends SurfaceView implements Callback{ //用于控制SurfaceView private SurfaceHolder sfh; private Handler handler = new Handler();

  • Android中SurfaceView和view画出触摸轨迹

    一.引言          想实现一个空白的画板,上面可以画出手滑动的轨迹,就这么一个小需求.一般就来讲就两种实现方式,view或者surfaceview.下面看看两种是如何实现的. 二.实现原理          先简单说一下实现原理:        (1)用一张白色的Bitmap作为画板        (2)用canvas在bitmap上画线        (3)为了画出平滑的曲线,要用canvas的drawPath(Path,Paint)方法.        (4)同时使用贝塞尔曲线来使曲

  • Android提高之SurfaceView的基本用法实例分析

    前文介绍了Android中MediaPlayer用法的时候稍微介绍了SurfaceView,SurfaceView由于可以直接从内存或者DMA等硬件接口取得图像数据,因此是个非常重要的绘图容器,这次我就来较为详细的介绍SurfaceView的用法.网上介绍SurfaceView的用法有很多,写法也层出不同,例如继承SurfaceView类,或者继承SurfaceHolder.Callback类等,这个可以根据功能实际需要自己选择,本文所述方法就直接在普通的用户界面调用SurfaceHolder的

  • Android利用SurfaceView实现下雨的天气动画效果

    首先是最终实现的效果图: 先分析一下雨滴的实现: 每个雨滴其实就是一条线,通过 canvas.drawLine() 绘制 线(雨滴)的长度.宽度.下落速度.透明度以及位置都是在一定范围内随机生成 每 draw 一次然后改变雨滴的位置然后重绘即可实现雨滴的下落效果 分析完了,那么可以直接写一个类直接继承 View ,然后重写 onDraw() 吗?可以看到效果图中的雨滴的下落速度很快,那么意味着每一帧都要调用 onDraw() 一次使其重新绘制一次,假如你的 onDraw() 方法里面的渲染代码稍

  • Android App中使用SurfaceView制作多线程动画的实例讲解

    1. SurfaceView的定义 通常情况程序的View和用户响应都是在同一个线程中处理的,这也是为什么处理长时间事件(例如访问网络)需要放到另外的线程中去(防止阻塞当前UI线程的操作和绘制).但是在其他线程中却不能修改UI元素,例如用后台线程更新自定义View(调用View的在自定义View中的onDraw函数)是不允许的. 如果需要在另外的线程绘制界面.需要迅速的更新界面或则渲染UI界面需要较长的时间,这种情况就要使用SurfaceView了.SurfaceView中包含一个Surface

  • Android中SurfaceView用法简单实例

    本文实例讲述了Android中SurfaceView用法.分享给大家供大家参考,具体如下: 这里贴上一个小程序代码,主要运用SurfaceView来实现在屏幕上画一个圆,你可以通过按方向键和触摸屏幕来改变圆的位置 代码: Activity: package com.view; import android.app.Activity; import android.os.Bundle; import android.view.Window; import android.view.WindowMa

  • Android编程之SurfaceView学习示例详解

    本文实例讲述了Android编程之SurfaceView学习示例.分享给大家供大家参考,具体如下: SurfaceView是View的子类,使用的方式与任何View所派生的类都是完全相同的,可以像其他View那样应用动画,并把它们放到布局中. SurfaceView封装的Surface支持使用本章前面所描述的所有标准Canvas方法进行绘图,同时也支持完全的OpenGL ES库. 使用OpenGL,你可以再Surface上绘制任何支持的2D或者3D对象,与在2D画布上模拟相同的效果相比,这种方法

  • 基于SurfaceView实现可拖动视频控件

    本文实例为大家分享了基于SurfaceView的可拖动视频控件,供大家参考,具体内容如下 public class DragSurfaceView extends SurfaceView implements View.OnTouchListener { protected int screenWidth; protected int screenHeight; protected int lastX; protected int lastY; private int oriLeft; priv

  • Android基于widget组件实现物体移动/控件拖动功能示例

    本文实例讲述了Android基于widget组件实现物体移动/控件拖动功能.分享给大家供大家参考,具体如下: package com.sky; import android.app.Activity; import android.os.Bundle; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickLi

  • 基于C# wpf 实现Grid内控件拖动详情

    目录 一.如何实现? 1.注册鼠标事件 2.记录位置 3.跟随鼠标移动 4.恢复标识 二.示例 前言: 有一些业务场景中我们需要拖动控件,在Grid中就可以实现控件拖动,通过设置Margin属性即可,根据鼠标的移动,设置相应的Margin的Left.Top,当然有时也不是直接设置的,需要根据HorizontalAlignment.VerticalAlignment值有不同的计算方法. 一.如何实现? 1.注册鼠标事件 拖动的控件需要注册3个鼠标事件分别是,鼠标按下.鼠标移动.鼠标弹起. 以But

  • 基于Bootstrap仿淘宝分页控件实现代码

    大家都应该上过淘宝的吧,没有上过淘宝的同学估计也没几个了,但是我相信大多数的人都是在淘宝上面买完东西就下线,很少有人会关注淘宝上的设计这类的,但是对于普通人这样还行,但是对于一个程序员这样就可不行了,因为博主本人是从事前端方面的工作,所以就通过仿照淘宝的设计样式,以求在技能上面能够有一个大的突破 一.淘宝分页控件了解 先上一张淘宝的分页图片: 根据上图中对淘宝分页控件的分析,我们大致上可以将淘宝分页控件分成两部分,一部分是核心部分,这一部分主要就是一个分页的核心功能,这个功能同时也是也是不可或缺

  • Android中SeekBar拖动条控件使用方法详解

    SeekBar拖动条控件使用方法,具体内容如下 一.简介 1.  二.SeekBar拖动条控件使用方法 1.创建SeekBar控件 <SeekBar android:id="@+id/SeekBar1" android:layout_width="match_parent" android:layout_height="wrap_content" android:progress="30" /> 2.添加setOn

  • Android开发之基于RecycleView实现的头部悬浮控件

    RecyclerView是一种类似于ListView的一个滑动列表,但是RecyclerView和ListView相比,RecyclerView比ListView更好,RecyclerView支持横向滑动,RecyclerView没有点击事件,需要自己加入,还可以做出各种炫酷的效果动画,更符合高内聚低耦合, 前言 前几天看到一个RecycleView中筛选框滑动可以悬浮在头部的效果类似商机盒子中的商机模块. 本来想法很常规 通过Recycview装饰器来实现(刚开始是否定掉的感觉太难) 通过Re

  • Qt实现拖动单个控件移动的示例代码

    目录 1.设置窗口拖拽属性 2.创建初始控件 3.选中控件进行拖动 3.1响应mousePressEvent事件 3.2判断控件拖动 3.3事件处理 3.4结束拖动 做惯了静态图,今天来搞一搞动态图吧,首先来个最基础的功能:如果让一个控件拖动起来. 展示效果: 按照以往简单的做法,使用mouseMoveEvent.mousePressEvent.mouseReleaseEvent也是可以实现的.这是最基础的移动做法. 今天,不使用那种简单的做法,采用Qt一种特有的拖动方法来实现! 使用QDrop

  • Android开发自定义双向SeekBar拖动条控件

    目录 目标:双向拖动的自定义View 实现步骤 自定义属性获取 确定自定义view尺寸 绘制相关的内容部分 滑动事件处理 目标:双向拖动的自定义View 国际惯例先预览后实现 我们要实现的就是一个段位样式的拖动条,用来做筛选条件用的,细心的朋友可能会发现微信设置里面有个一个通用字体的设置,拖动然后改变字体大小; 这个相对比微信那个的自定义view算是一个扩展,因为我们是双向滑动,这个多考虑的一点就是手指拖动的是哪一个滑动块! 我们先看下GIF预览,然后我们今天就一步步实现这个小玩意… 实现步骤

  • java制作仿微信录制小视频控件

    本文为用 MediaRecorder 录制小视频的控件,可以设置视频录制的时间.空间大小.初始时是否打开摄像头等. 此控件为组合控件,继承自 LinearLayout ,为防止出错,需实现 android.media.MediaRecorder.OnErrorListener 接口. 小视频录制界面 MovieRecorderView.java import java.io.File; import java.io.IOException; import java.util.Timer; imp

  • 基于jquery实现简单的分页控件

    前台分页控件有很多,这里分享我的分页控件 pagination.js 1.0版本,该控件基于jquery. 先来看一下预览效果: 默认情况下,点击页码会像博客园一样,在url后面加上"#p页码". 控件有2个参数需要注意: 1. beforeRender: 在每个页码项呈现前会被调用,参数为页码的jQuery对象.这个时候我们可以在呈现前做一些处理,例如增加自己的属性等.默认情况下,点击页码,会在url后面加上"#p页码",这样的url并不会刷新页面.如果我们需要刷

随机推荐