这是一个简单的电影院选座效果,实现该效果大致分为三步:
  1. 自定义view进行绘制;
  2. 手势缩放效果的实现;
  3. 手势触摸被选和未被选效果的实现;

先来看第一步,效果的绘制;

public class MoveSeatView extends View {private final boolean DBG = false;private Paint paint = new Paint();private Matrix matrix = new Matrix();private Matrix tempMatrix = new Matrix();//座位水平间距private int spacing;//座位垂直间距private int verSpacing;//行号宽度private int numberWidth;//行数private int row;//列数private int column;//可选座位的图片private Bitmap seatBitmap;//选中时座位的图片private Bitmap checkedSeatBitmap;private int lastX;private int lastY;//整个座位图的宽度private int seatBitmapWidth;private int seatBitmapHeight;private float screenHeight;//屏幕的最小宽度private int defaultScreenWidth;//标识是否正在缩放private boolean isScaling;private float scaleX, scaleY;//是否是第一次缩放private boolean firstScale = true;private boolean isOnClick;private int downX, downY;private boolean pointer;//用于存储已经选在好的座位public ArrayList<Point> list;/*** 默认的座位图片的宽度,如果使用的自己的座位的图片比这个尺寸大或者小,会缩放到这个大小*/private float defaultImgW = 40;private float defaultImgH = 34;/*** 座位图片的宽度*/private int seatWidth = 40;/*** 座位图片的高度*/private int seatHeight = 34;private float zoom;float xScalel = 1;float yScalel = 1;public MoveSeatView(Context context) {this(context, null);}public MoveSeatView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public MoveSeatView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}private void init() {spacing = (int) dip2px(5);verSpacing = (int) dip2px(10);defaultScreenWidth = (int) dip2px(80);seatBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.seat_default);xScalel = defaultImgW / seatBitmap.getWidth();yScalel = defaultImgH / seatBitmap.getHeight();checkedSeatBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.seat_green);seatBitmapWidth = (int) (column * seatBitmap.getWidth() * xScalel + (column - 1) * spacing);seatBitmapHeight = (int) (row * seatBitmap.getHeight() * yScalel + (row - 1) * verSpacing);paint.setColor(Color.RED);numberWidth = (int) dip2px(20);screenHeight = dip2px(20);list = new ArrayList<>();matrix.postTranslate(numberWidth + spacing, screenHeight + 1 + verSpacing);}
}

上面这些都是一些初始化动作,接下来在onDraw方法中进行绘制;

@Overrideprotected void onDraw(Canvas canvas) {if (row <= 0 || column <= 0) {return;}drawSeat(canvas);super.onDraw(canvas);}

具体的绘制逻辑实在drawSeat(),方法中实现的;

/*** 绘制** @param canvas*/private void drawSeat(Canvas canvas) {zoom = getMatrixScaleX();float translateX = getTranslateX();float translateY = getTranslateY();float scaleX = zoom;float scaleY = zoom;for (int i = 0; i < row; i++) {float top = i * seatBitmap.getHeight() * yScalel * scaleY + i * verSpacing * scaleY + translateY;float bottom = top + seatBitmap.getHeight() * yScalel * scaleY;for (int j = 0; j < column; j++) {float left = j * seatBitmap.getWidth() * xScalel * scaleX + j * spacing * xScalel * scaleX + translateX;float right = left + seatBitmap.getWidth() * xScalel * scaleX;tempMatrix.setTranslate(left, top);tempMatrix.postScale(xScalel, yScalel, left, top);tempMatrix.postScale(scaleX, scaleY, left, top);if (isHave(i, j)) {//绘制被选canvas.drawBitmap(checkedSeatBitmap, tempMatrix, paint);//绘制文字drawText(canvas, i, j, top, left);} else {//绘制普通canvas.drawBitmap(seatBitmap, tempMatrix, paint);}}}}

主要是计算绘制的位置,矩阵的缩放,根据是否被选进行绘制不同的效果;

/*** 绘制文字** @param canvas* @param row* @param column* @param top* @param left*/private void drawText(Canvas canvas, int row, int column, float top, float left) {String txt = (row + 1) + "排";String txt1 = (column + 1) + "座";//实例化文字画笔TextPaint txtPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);txtPaint.setColor(Color.WHITE);//设置字体样式txtPaint.setTypeface(Typeface.DEFAULT_BOLD);float seatHeight = this.seatHeight * getMatrixScaleX();float seatWidth = this.seatWidth * getMatrixScaleX();txtPaint.setTextSize(seatHeight / 3);//获取中间线float center = seatHeight / 2;float txtWidth = txtPaint.measureText(txt);float startX = left + seatWidth / 2 - txtWidth / 2;//只绘制一行文字if (txt1 == null) {canvas.drawText(txt, startX, getBaseLine(txtPaint, top, top + seatHeight), txtPaint);} else {canvas.drawText(txt, startX, getBaseLine(txtPaint, top, top + center), txtPaint);canvas.drawText(txt1, startX, getBaseLine(txtPaint, top + center, top + center + seatHeight / 2), txtPaint);}if (DBG) {Log.d("drawTest", "top" + top);}}

这里是使用TextPaint画笔进行文字的绘制,在绘制文字的时候要注意基准线;

/*** 获取基准线* @param p* @param top* @param bottom* @return*/private float getBaseLine(Paint p, float top, float bottom) {Paint.FontMetrics fontMetrics = p.getFontMetrics();int baseLine = (int) ((bottom + top - fontMetrics.bottom - fontMetrics.top) / 2);return baseLine;}

这样大致的绘制做完成了,剩下的第二步和第三步都涉及到手势触摸,在onTouchEvent方法中去实现具体的逻辑;

@Overridepublic boolean onTouchEvent(MotionEvent event) {int x = (int) event.getX();int y = (int) event.getY();//手势缩放scaleGuestureDetector.onTouchEvent(event);//手势gestureDetector.onTouchEvent(event);//获取当前操作的手指数量int pointerCount = event.getPointerCount();if (pointerCount > 1) {//多手指操作pointer = true;}switch (event.getAction()) {case MotionEvent.ACTION_DOWN:pointer = false;downX = x;downY = y;invalidate();break;case MotionEvent.ACTION_UP:autoScale();break;case MotionEvent.ACTION_MOVE:if (!isScaling && !isOnClick) {int downDX = Math.abs(x - downX);int downDY = Math.abs(y - downY);if ((downDX > 10 || downDY > 10) && !pointer) {int dx = x - lastX;int dy = y - lastY;matrix.postTranslate(dx, dy);invalidate();}}lastX = x;lastY = y;isOnClick = false;break;}return true;}

刚触摸去选择的时候会有个手势缩放的效果,手势缩放系统提供了ScaleGestureDetector类可以很容易的实现,具体的逻辑系统都已经处理好了,在对应的回调方法里面去实现就可以了;

/*** 手势缩放*/ScaleGestureDetector scaleGuestureDetector = new ScaleGestureDetector(getContext(), new ScaleGestureDetector.OnScaleGestureListener() {@Overridepublic boolean onScale(ScaleGestureDetector detector) {//正在缩放的时候回调isScaling = true;float scaleFactor = detector.getScaleFactor();if (getMatrixScaleY() * scaleFactor > 3) {scaleFactor = 3 / getMatrixScaleY();}if (firstScale) {scaleX = detector.getCurrentSpanX();scaleY = detector.getCurrentSpanY();firstScale = false;}if (getMatrixScaleY() * scaleFactor < 0.5) {scaleFactor = 0.5f * getMatrixScaleY();}matrix.postScale(scaleFactor, scaleFactor, scaleX, scaleY);invalidate();return true;}@Overridepublic boolean onScaleBegin(ScaleGestureDetector detector) {//开始缩放的时候回调return false;}@Overridepublic void onScaleEnd(ScaleGestureDetector detector) {//缩放完成回调isScaling = false;firstScale = true;}});

其他的手势操作系统还提供了GestureDetector类,可以使用GestureDetector来实现具体的效果;

GestureDetector gestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {@Overridepublic boolean onSingleTapConfirmed(MotionEvent e) {int x = (int) e.getX();int y = (int) e.getY();for (int i = 0; i < row; i++) {for (int j = 0; j < column; j++) {int tempX = (int) ((j * seatWidth + j * spacing) * getMatrixScaleX() + getTranslateX());int maxTempX = (int) (tempX + seatWidth * getMatrixScaleX());int tempY = (int) ((seatHeight * i + i * verSpacing) * getMatrixScaleY() + getTranslateY());int maxTempY = (int) (tempY + seatHeight * getMatrixScaleY());if (x >= tempX && x <= maxTempX && y >= tempY && y <= maxTempY) {if (isHave(i, j)) {remove(i, j);} else {list.add(new Point(i, j));}}}}float currentScaleY = getMatrixScaleY();if (currentScaleY < 1.7) {scaleX = x;scaleY = y;zoomAnimate(currentScaleY, 1.9f);}invalidate();return true;}});

完成上面三步,效果也就大致实现了,提供外部设置的方法供调用就可以了;

/*** 对外界提供的设置方法* @param row* @param column*/public void setData(int row, int column) {this.row = row;this.column = column;init();invalidate();}

源码地址:

https://pan.baidu.com/s/1JH-HQ6_sVE1sqtTtALydOw

简单实现电影院选座效果相关推荐

  1. css实现简单的电影院选座功能

    实现原理:把每个座位看成一个对象,可以添加自己要的属性.每一行是一个数组,有多个座位对象.总数也是一个数组,包含多行. <template><div>请输入宽度:<el- ...

  2. java简单的控制台电影院选座系统

    java简单的控制台电影院选座系统 已经自学快一个多月的java(复习),来回顾一下 最开始的数组与循环-加群(一个学习方法教育的视频群)时我已经按照自己的方法学习半个月了,看到视频说要验证自己是否已 ...

  3. 基于微信小程序电影院选座订票系统 计算机毕设源码26840

    摘  要 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,电影院选座订票系统小程序被用户普遍使用,为方 ...

  4. android studio电影院选座,8排电影院选座最佳位置

    8排电影院选座最佳位置在哪里呢?8排电影院属于小影厅,小影厅银幕宽度在10米以下,座位100以内,座位排数通常拥有8-14排,小影厅整体空间小,选座时要选中间稍靠后一些的位置.由于整体排数少,因此选即 ...

  5. Java----使用二维数组完成一个电影院选座系统

    用Java的二维数组来完成模拟一个电影院选座系统 模拟座位 这里先定义一个二维数组,用来模拟电影院的座位 public class ChooseSeat{public static void main ...

  6. php 影院选座js代码,在react中用canvas做一个电影院选座功能

    又到了每日分享了.这次分享的是:在react中用canvas做一个电影院选座功能. 前言:项目采用create-react-app脚手架,就是做了一个效果所以只有一个页面但是也用了react-rout ...

  7. 电影院选座问题----go

    电影院选座问题----go 题目 思路 代码 复杂度分析 题目 抖音电影票业务支持电影院选座,需要在用户买票时自动推荐座位,如果一个用户买了多张票,则需要推荐相邻(上下相邻.左右相邻都可)的座位.现在 ...

  8. php实现猫眼电影院选座思路,高仿猫眼电影选座(选票)模块

    前言: 高仿猫眼选票模块,看着猫眼app选票模块做的如此之帅,网上又没比较好的库,自己手痒痒了就开始模仿起来了,最终用了几天时间实现了,也封装好了一套选座模块. 上图看效果先: 1)画座位图其实不是很 ...

  9. 基于JSP后台的电影院选座售票小程序 毕业设计毕设作品欣赏

    (1)登录功能:注册普通账号登录:也可以直接使用微信登录:登录后可以修改用户的基本信息,也可以退出. (2)资讯功能:后台录入资讯,在微信小程序电影院订票选座系统的资讯模板展示,用户可以任意浏览资讯列 ...

最新文章

  1. angularjs2 html转义,详解Angular.js数据绑定时自动转义html标签及内容
  2. k8s 去除master节点污点NoSchedule,添加master节点 尽量不调度
  3. c++一日一练:利用流来实现读和写的同步(原创)
  4. 认证连接_长江连接器哪些产品通过认证?
  5. RHEL6 cryptsetup 磁盘分区加密实验
  6. Codeforces Round #701 (Div. 2) C. Floor and Mod 数学分块
  7. c 站点下html页面拦截器,HTML内容拦截器「HTML Content Blocker」
  8. Java虚拟机专题之class文件结构(读书笔记)
  9. python3.8如何安装jieba库_安装jieba、wordcloud等第三方库
  10. 淘宝电影“追杀”猫眼电影,同门相争不可避免
  11. 自动化产线自动刀补实现
  12. 【1.01】VBA基础
  13. AMD黑苹果 3A平台EFI分享给大家
  14. Windows上值得一用的软件
  15. 学习全栈在线教育实战项目(尚硅谷) 第一天
  16. 生成SIN波形的一个小工具
  17. MTK工具sigma的使用
  18. 用javascript分类刷leetcode3.动态规划(图文视频讲解)
  19. 2005-04-21
  20. SQL知识点--插入记录

热门文章

  1. 亚马逊云科技 build on - 实验20220806
  2. 28335 warning: Data is being written to auto-generated file TMS32F28035_DEMO.i10
  3. 音响器材输出、输入连接的平衡与非平衡接驳端口问题
  4. LeetCode整理----合集一
  5. 计算机教育部第四次学科评估结果,【重磅!】全国高校第四轮学科评估结果出炉(附完整名单)...
  6. 2019年12月四六级百度云
  7. 笔记本win10引用账户当前已锁定,且可能无法登录(已解决)
  8. 正则判断变量是否为英文单词
  9. 【渝粤题库】国家开放大学2021春2006经济数学基础12题目
  10. RxJS 新手快速入门