Android打造炫酷的电影票在线选座app在线选座功能_Android

不知道大家有没有用过,淘宝电影客户端(淘票票)买过电影票,纵观各类在线选座app的在线选座功能 淘宝在线选座功能用户体验最好,用起来最顺手,夸张点说已经到了炉火纯青的地步,下面我们看一下效果:

效果分析:

整个控件分成几个部分,座位图区域、座位缩略图区域、行号区域、屏幕区域

1、座位图可以自由的移动缩放,放大缩小移动后会自动回弹到合适的位置,选中座位会自动放大到合适比例。

2、行号部分跟着座位图缩放以及上下移动,屏幕区域跟着座位图左右移动缩放。

3、当手指按下的时候会出现缩略图,缩略图上有个红色的方框表示,当前能看到的区域,并且跟随缩略图的移动。

涉及到的知识点:

view的绘制原理、事件分发机制这些就不说了,这些是基础,这里并不打算介绍,网上有非常多的这方面的资料。

1、矩阵Matrix使用,通过Matrix来进行移动、缩放

2、弹性移动、弹性缩放。

3、手势监听的使用通过GestureDetector、ScaleGestureDetector来获得缩放比例幅度。

编码实现

通过以下几个核心部分来介绍,其他部分都是类似的思路实现

1、绘制座位图

2、座位图的缩放和移动

3、座位图自动回弹、自动缩放

4、缩略图部分的绘制实现

至于其他部分比如影院荧幕,左侧的行号部分思路跟座位图的实现思路是一致的。

1、绘制座位图

座位图实际上就是个二维矩阵,有行数和列数,我们只需要根据行数和列数加上一定的间距绘制即可。

void drawSeat() {
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
int left = j * seatBitmap.getWidth() + j * spacing;
int top = i * seatBitmap.getHeight() + i * verSpacing;
int seatType = getSeatType(i, j);
switch (seatType) {
case SEAT_TYPE_AVAILABLE:
seatCanvas.drawBitmap(seatBitmap, left, top, paint);
break;
case SEAT_TYPE_NOT_AVAILABLE:
break;
case SEAT_TYPE_SELECTED:
seatCanvas.drawBitmap(checkedSeatBitmap, left, top, paint);
break;
case SEAT_TYPE_SOLD:
seatCanvas.drawBitmap(seatSoldBitmap, left, top, paint);
break;
}
}
}
isNeedDrawSeatBitmap = false;
}

getSeatType()方法是用来判断当前的座位是否可用,是否已经卖出去,是否已经选中,根据这些状态绘制不同的座位图。

2、座位图的缩放和移动

移动缩放功能使用 Matirx来实现,Matrix在android中可以用来对图片进行缩放、移动、旋转等变换。
matrix本身是一个3*3的矩阵,矩阵中的每一个值都代表一个变换属性,如下

MSCALE_X MSKEW_X MTRANS_X
MSKEW_Y MSCALE_Y MTRANS_Y
MPERSP_0 MPERSP_1 MPERSP_2

实际上就是一个有9个元素的数组

float[] value=new float[9]; 

通过 matrix.getValues(value);可以获得具体的值。

value[0]表示的是缩放的x值

value[1]表示的是斜切的x值

value[2] 表示x轴上平移的值

value[3]表示的是斜切的y值

value[4]表示的y轴上的缩放比例

value[5]表示的是y轴上的平移的值

Matrix类有一些方法可以对这些值进行改变

setScale(float sx, float sy, float px, float py) :设置x轴和y周上的缩放比例,px,py表示缩放的中心点。

setTranslate(float dx, float dy) :设置x轴和y周上的偏移量。

与之对应的还有这么两个方法:

postScale(float sx, float sy, float px, float py)
postTranslate(float dx, float dy) 

那么post跟set有什么区别呢,简单理解就是set直接,把之前的值给覆盖了,而post是在之前的值的基础上进行变换。比如现在你已经向左移动了10个像素,这时候你用setTranslate(5,5)这个时候直接变成了移动5个像素了,而用post就是在10的基础上在移动5个像素就变成15了。

以上是Matrix的使用方法,Canvas对象有个drawBitmap方法可以接收一个matrix,这样就可以在绘图的时候使用matrix进行变换了。

座位图平移缩放的实现思路:

要做两件事情来实现座位图的缩放移动

1、获取平移的值和放大缩小的比例

重写onTouchEvent方法来计算获取移动的x值和y值

使用ScaleGestureDetector这个类来帮我们获取放大缩小的比例,使用非常简单,创建一个ScaleGestureDetector的对象,然后在onTouchEvent方法了调用一下ScaleGestureDetector.onTouchEvent(event);即可

2、根据获取到的值对座位图进行平移和缩放

获取到了平移的值和缩放的比例后,使用matrix.postScale(x,y)和matrix.postTrans(x,y)进行对应的变换即可,变换完了调用view的invalidate方法让view重新绘制matrix即可生效。

下面只列出了核心代码,省掉了一些逻辑,完整代码请到github中查看。

ScaleGestureDetector scaleGestureDetector = new ScaleGestureDetector(getContext(), new ScaleGestureDetector.OnScaleGestureListener() {
@Override
public boolean onScale(ScaleGestureDetector detector) {
float scaleFactor = detector.getScaleFactor();
matrix.postScale(scaleFactor, scaleFactor, scaleX, scaleY);
invalidate();
return true;
}
});

onTouchEvent处理逻辑

@Override
public boolean onTouchEvent(MotionEvent event) {
int y = (int) event.getY();
int x = (int) event.getX();
scaleGestureDetector.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = x;
downY = y;
break;
case MotionEvent.ACTION_MOVE:
int downDX = Math.abs(x - downX);
int downDY = Math.abs(y - downY);
if (downDX > 10 || downDY > 10) {
int dx = x - lastX;
int dy = y - lastY;
matrix.postTranslate(dx, dy);
invalidate();
}
break;
case MotionEvent.ACTION_UP:
....
break;
}
lastY = y;
lastX = x;
return true;
}

onDraw的时候

@Override
protected void onDraw(Canvas canvas) {
.....
canvas.drawBitmap(seat, matrix, paint);
.....
}

3、座位图的自动回弹、自动缩放效果的实现

为什么要自动回弹呢,因为你操作的时候有可能把座位图移到屏幕外,缩放的时候把图缩放的比较小,或者比较大,这个时候程序通过计算给你自动的移动到一个比较合适的位置,比较合适的缩放大小。这样就有着不错的使用体验。

自动回弹实现的思路:

当我们手指屏幕上移动然后抬起的时候会触发MotionEvent.ACTION_UP事件,这个时候我们可以通过matrix对象来获取当前的移动的位置,如果当前移动的值不符合我们的规则,我们就将座位图按照规则移动到指定位置。

移动规则如下(参考的淘票票客户端的移动逻辑)

座位图整个大小不超过控件大小的时候:

往左边滑动,自动回弹到行号右边

往右边滑动,自动回弹到右边

往上,下滑动,自动回弹到顶部

座位图整个大小超过控件大小的时候:

往左侧滑动,回弹到最右边,往右侧滑回弹到最左边

往上滑动,回弹到底部,往下滑动回弹到顶部

以上的移动规则的实现大家可以查看具体源码中的autoScroll()方法的实现,这里就不贴出来了。

移动和缩放涉及到一个弹性移动和缩放的问题,所谓弹性移动就是有动画效果的移动。因为如果你当前在100,100 这个位置,你需要移动到800,100这个位置,如果你直接移动到800这个位置,而不是通过,先移动到110,在移动到120。。。一直到800这样一段一段的移动。那么移动效果将是非常僵硬的,刷的闪过去的感觉,效果非常不好。

弹性移动的实现思路就是:

比如要从100,100 移动到800,100这个位置,很明显 x轴要移动700个像素。那么把这700个像素的移动我们分成10次移动来实现,每次移动700/10=70个像素,两次移动之间间隔50毫秒,就跟帧动画似的,这样就会有一个弹性的动画效果。

通过handler来实现代码如下:

int FRAME_COUNT = 10;
int time = 15;
int count;
Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (count < FRAME_COUNT) {
count++;
MoveInfo moveInfo = (MoveInfo) msg.obj;
float moveXLength = moveInfo.moveXLength;
float moveYLength = moveInfo.moveYLength;
float xValue = moveXLength / FRAME_COUNT;
float yValue = moveYLength / FRAME_COUNT;
matrix.postTranslate(xValue, yValue);
invalidate();
Message message = Message.obtain();
message.obj = msg.obj;
//循环调用
handler.sendMessageDelayed(message, time);
} else {
count = 0;
}
return true;
}

弹性缩放的原理跟弹性移动的原理一致

4、缩略图部分的绘制实现

缩略图是座位图的缩小版,缩略图的宽高和座位图的宽高有一定比例,比如五分之一。当然这是可以根据效果来调整的。之所以必须是座位图的一定比例,是因为缩略图上有一个动态的红色方框表示当前可见的座位区域,这个红色方框是需要根据座位图的移动而移动的。比例确定后,就这可以根据座位图的移动来移动红色方框。举个例子来说-如果当前座位图向上移动了100个像素,那么缩略图中对应的红色方框部分向下移动 100/4=250个像素即可。

绘制概览图代码:

Bitmap drawOverview() {
//计算概览图上代表座位的正方形宽度、高度
//规则 :座位图上座位的宽度/缩放比例
float rectSize = seatBitmap.getHeight() / overviewScale;
//计算概览图的宽度和高度
rectW = column * rectWidth + (column - 1) * overviewSpacing + overviewSpacing * 2;
rectH = row * rectSize + (row - 1) * overviewVerSpacing + overviewVerSpacing * 2;
Canvas canvas = new Canvas(overviewBitmap);
//绘制透明灰色背景
canvas.drawRect(0, 0, rectW, rectH, paint);
paint.setColor(Color.WHITE);
//循环绘制
for (int i = 0; i < row; i++) {
float top = i * rectSize + i * overviewVerSpacing + overviewVerSpacing;
for (int j = 0; j < column; j++) {
//获取座位是什么状态 已经售出、未选中、已经选中
int seatType = getSeatType(i, j);
switch (seatType) {
case SEAT_TYPE_AVAILABLE:
paint.setColor(Color.WHITE);
break;
case SEAT_TYPE_NOT_AVAILABLE:
continue;
case SEAT_TYPE_SELECTED:
paint.setColor(overview_checked);
break;
case SEAT_TYPE_SOLD:
paint.setColor(overview_sold);
break;
}
float left;
left = j * rectWidth + j * overviewSpacing + overviewSpacing;
canvas.drawRect(left, top, left + rectWidth, top + rectSize, paint);
}
}
return overviewBitmap;
}

绘制概览图上的红色方框

/**
* 绘制概览图
*/
void drawOverviewBorder(Canvas canvas) {
//绘制红色框
int left = (int) -getTranslateX();//获取当前座位图x轴上的平移位置
if (left < 0) {
left = 0;
}
left /= overviewScale; //overviewScale 表示概览图占座位图的比例
left /= getMatrixScaleX();//getMatrixScaleX() 获取当前座位图的缩放比例
//判断当前座位图的宽度是否超出 整个控件的宽度,如果超出了,那么超出的部分就看不见。表示当前能看到的位置的红色方框就不能把超出的部分框进来。
int currentWidth = (int) (getTranslateX() + (column * seatBitmap.getWidth() + spacing * (column - 1)) * getMatrixScaleX());
if (currentWidth > getWidth()) {
currentWidth = currentWidth - getWidth();
} else {
currentWidth = 0;
}
int right = (int) (rectW - currentWidth / overviewScale / getMatrixScaleX());
float top = -getTranslateY()+headHeight;
if (top < 0) {
top = 0;
}
top /= overviewScale;
top /= getMatrixScaleY();
if (top > 0) {
top += overviewVerSpacing;
}
//判断当前座位图的宽度是否超出 整个控件的高度,如果超出了,那么超出的部分就看不见。表示当前能看到的位置的红色方框就不能把超出的部分框进来。
int currentHeight = (int) (getTranslateY() + (row * seatBitmap.getHeight() + verSpacing * (row - 1)) * getMatrixScaleY());
if (currentHeight > getHeight()) {
currentHeight = currentHeight - getHeight();
} else {
currentHeight = 0;
}
int bottom = (int) (rectH - currentHeight / overviewScale / getMatrixScaleY());
canvas.drawRect(left, top, right, bottom, redBorderPaint);
}

控件性能优化

千辛万苦终于把控件做出来了,结果一运行卡的不要不要的。特别是行数列数一多,卡顿的懵逼了。这个时候呢我们要对性能进行优化,总结下来主要从以下几个方面:

1、避免在onDraw中创建对象,分配内存,把paint对象的创建放在初始化函数里面。这一步其实非常重要因为我们使用canvas绘图的时候需要paint对象,往往不同的地方需要不同paint,这样一来,创建的paint对象就比较多了,在加上onDraw方法可能会执行多次。频繁的创建对象会造成gc,导致卡顿。当然了不止是paint对象,其他的对象创建也要能少则少。

2、避免不必要的绘制逻辑,在需要的时候才绘制。这个需要我们根据控件的绘制逻辑来进行调整,同样也是非常重要。

3、总的原则就是想尽一切办法把onDraw方法的执行控制在16ms以内,就不会卡了。

最后看看我们实现的效果

源码地址:

github地址

以上所述是小编给大家介绍的Android打造炫酷的电影票在线选座app在线选座功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索android
电影票在线选座
ps打造炫酷字体、ps打造炫酷战场、android炫酷动画效果、android 炫酷动画、android炫酷的loading,以便于您获取更多的相关知识。

时间: 2024-08-22 15:13:18

Android打造炫酷的电影票在线选座app在线选座功能_Android的相关文章

Android打造炫酷进度条效果

本文实例为大家分享了Android炫酷进度条效果的具体代码,供大家参考,具体内容如下 学习:视频地址 HorizontalProgressbarWithProgress的代码 import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.os.Build; imp

如何运用光线效果来打造炫酷的视觉画面效果

  此教程,我们将会学习在图片中如何运用光线效果来打造炫酷的视觉画面效果.在制作的过程中将运用:混合模式,画笔预设,动感模糊.创建剪贴蒙版,渐变.滤镜.色彩调整等,同时也用到一些纹理图片.在做的过程中我们也可以根据自己的感官和视觉上的喜爱做出不同的时尚炫酷效果分享给周围的朋友. 最终预览效果 1.Step 选择一张漂亮的模特图片,我习惯用钢笔工具选中人物,头发使用通道抠图,当然在网上有很多抠图的实用性教程,这里用到的 只是其中的一部分. 2.Step 新建图层,制作如图渐变图层;或下载背景图片(

JQuery和CSS打造炫酷动感菜单

本教程将分步讲解如何使用JQuery和CSS打造一个炫酷动感菜单.jQuery的"write less, do more"的特性可谓是家喻户晓,即使没有很丰富JS编程经验的人,也可以通过其提供的API很快学会如何使用,当然,如果您经验丰富,我还是建议您可以理解jQuery各主要函数的实现原理,其他不说了,直接看看如何用它来实现菜单神奇的效果吧 您可以点击查看演示,也可以点击下载源代码. Step1 - HTML结构 看一下菜单的HTML代码,跟平常的菜单代码没有什么区别:  <d

ps打造炫酷的iPhone手机天空之城

在今天的photoshop合成教程里,我们将教大家在photoshop中使用一些笔刷和图片设计一个炫酷的苹果手机天空之城的效果. 在今天的photoshop合成教程里,我们将教大家在photoshop中使用一些笔刷和图片设计一个炫酷的苹果手机天空之城的效果.同时还要用到的技术有像选区.蒙板.画笔还有一些小技巧来使这个教程更加有趣和壮观. 我们所做的最终效果图: 下面所列的一些图片.笔刷就是我们将会使用到的,当然你可以有自己的偏好. 所需的素材: Iphone image Grass image

Android实现炫酷的网络直播弹幕功能_Android

现在网络直播越来越火,网络主播也逐渐成为一种新兴职业,对于网络直播,弹幕功能是必须要有的,如下图: 首先来分析一下,这个弹幕功能是怎么实现的,首先在最下面肯定是一个游戏界面View,然后游戏界面上有弹幕View,弹幕的View必须要做成完全透明的,这样即使覆盖在游戏界面的上方也不会影响到游戏的正常观看,只有当有人发弹幕消息时,再将消息绘制到弹幕的View上面就可以了,下方肯定还有有操作界面View,可以让用户来发弹幕和送礼物的功能,原理示意图如下所示: 参照原理图,下面一步一步来实现这个功能.

Android实现炫酷的CheckBox效果_Android

首先贴出实现的效果图: gif的效果可能有点过快,在真机上运行的效果会更好一些.我们主要的思路就是利用属性动画来动态地画出选中状态以及对勾的绘制过程.看到上面的效果图,相信大家都迫不及待地要跃跃欲试了,那就让我们开始吧. 自定义View的第一步:自定义属性. <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="SmoothChe

Android绘制炫酷引导界面_Android

一个超炫的引导界面,分享给大家 代码: MainActivity.java package com.bzu.gxs.webview1; import android.app.Activity; import android.os.Build; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.KeyEvent; import android.view.Men

Android实现炫酷的网络直播弹幕功能

现在网络直播越来越火,网络主播也逐渐成为一种新兴职业,对于网络直播,弹幕功能是必须要有的,如下图: 首先来分析一下,这个弹幕功能是怎么实现的,首先在最下面肯定是一个游戏界面View,然后游戏界面上有弹幕View,弹幕的View必须要做成完全透明的,这样即使覆盖在游戏界面的上方也不会影响到游戏的正常观看,只有当有人发弹幕消息时,再将消息绘制到弹幕的View上面就可以了,下方肯定还有有操作界面View,可以让用户来发弹幕和送礼物的功能,原理示意图如下所示: 参照原理图,下面一步一步来实现这个功能.

Photoshop打造炫酷的横幅海报

1. 新建一个895×307px的图层,分辨率为300,背景颜色为白色,颜色模式为RGB. 2. 打开人物素材,拖到刚刚新建的图层上面. 3.新建图层,使用钢笔工具圈出图片上半部分,需要带点弧度,然后使用快捷键ctrl+enter 使其进入选区. 4.选择渐变工具,设置渐变的颜色,并用吸管工具调整渐变颜色,颜色分别为:#a4dce7.#f8f7cf.#ea93d4 5.点击渐变菜单上面部分的色标,设置不透明度 6.然后选择线性渐变,拉个渐变出来,如果颜色太浓,可以使用橡皮擦工具稍微擦拭. 7.用