Android打造流畅九宫格抽奖活动效果

因为company项目中需要做九宫格抽奖活动,以前都没有做过类似的功能,虽然之前在浏览大神们的博客中,无意中也看到了好多关于抽奖的项目,但因为项目中没有需要,一直都没有点击进去看。这次不去看估计不行。直到公司计划要做抽奖功能,才迫不得已上网查找demo

网上找了大半天,好不容易找到了几个demo,下载下来,解压缩包发现竟然里面空空如也,只有几张九宫格的图片,害我白白浪费了几个CSDN积分。后面在eoe网站那发现了一个demo,于是好开心,下载下来后马上导入到工程中,运行看了效果,九宫格是出来了,但效果真不敢恭维,主要是运行不流畅。但我还是进去稍微看了一下demo,基本思路是这样的:定义好九宫格界面,然后开启子线程不断循环修改状态,再通过handler发送消息到主线程中修改界面(子线程不能直接修改界面)。

这个demo虽然功能上实现了,但不是我想要的效果,因为我这一关都不能通过,到了产品那边更加不用说了。那怎么办呢?

于是我想到了一个控件,叫做SurfaceView,做游戏开发的同志们,应该对这个控件不陌生吧?首先介绍一下这个控件:
1.SurfaceView继承于View,多用于游戏开发中
2.可以直接在子线程中运行(其他UI控件都必须在主线程中运行的)。
3.一般的UI控件自定义时都是重写onDraw方法,但在SurfaceView中是通过SurfaceHolder获取Canvas来绘制图形的

好了,来吧各位,先来看看效果图:

这样,下面我开始根据我的想法,把自定义九宫格的步骤说一下。

步骤:

1.计算各位方块的位置
2.绘制每个奖品的方块(主要让界面更加好看)
3.绘制奖品图
4.计算旋转方块的下一步位置
5.绘制旋转方块
6.监听点击开始按钮事件

主要核心技术:
SurfaceView,SurfaceHolder

OK,有了基本步骤,接下来就是根据步骤一步一步来进行了。
在开始绘制九宫格之前,我们先重写onMeasure方法,主要是为了让九宫格成为一个正方形,这样看起来体验更好,基本代码如下:

public class LotteryView extends SurfaceView{

  /**
   * holder
   */
  private SurfaceHolder mHolder;

  private List<Prize>prizes;
  private boolean flags;  //抽奖开关

  private int lottery=6;  //设置中奖号码

  private int current=2;  //抽奖开始的位置

  private int count=0;  //旋转次数累计

  private int countDown;  //倒计次数,快速旋转完成后,需要倒计多少次循环才停止

  //旋转抽奖的方块默认颜色
  private int transfer= 0xffff0000;

  private int MAX=50;  //最大旋转次数
  /**
   * 重新测量
   */
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
  {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int width = Math.min(getMeasuredWidth(), getMeasuredHeight());
    setMeasuredDimension(width, width);
  }
}

SurfaceView一般不是通过重写onDraw方法来绘制控件的,那么怎么获取到Canvas呢?主要是通过SurfaceHolder监听Callback事件来获取的
基本代码如下:

/**
   * holder
   */
  private SurfaceHolder mHolder;
  public LotteryView(Context context, AttributeSet attrs) {
    super(context, attrs);
    mHolder = this.getHolder();
    //监听CallBack
    mHolder.addCallback(this);
  }

  public LotteryView(Context context) {
    this(context,null);
  }

现在有了对象SurfaceHolder对象,我们就可以获取到Canvas对象了,下面开始真正的绘制工作。

1.计算方块的具体显示位置
2.绘制每个奖品的方块

  //绘制背景
  private void drawBg(Canvas canvas) {
    //清除已绘制的图形
    canvas.drawColor(Color.WHITE, Mode.CLEAR);
    //获取控件的宽度,因为要绘制九宫格,所以要平局分成三列
    int width = getMeasuredWidth()/3;
    int x1=0;
    int y1=0;

    int x2=0;
    int y2=0;

    int len = (int) Math.sqrt(prizes.size());

    for(int x=0;x<len*len;x++){

      Prize prize = prizes.get(x);

      int index=x;
      x1=getPaddingLeft()+width*(Math.abs(index)%len);
      y1=getPaddingTop()+width*(index/len);

      x2=x1+width;
      y2=y1+width;
      Rect rect=new Rect(x1,y1,x2,y2);

      Paint paint=new Paint();
      //绘制方块
      canvas.drawRect(rect, paint);
    }
  }

解析:prizes 是一个集合,里面封装了奖品的一些基本信息,x1,y1,x2,y2分别是绘制奖品容器正方形的左上顶点和右下顶点,

通过观察发现,每一个方块位置都有一定的关系,即 x1=getPaddingLeft()+width*(Math.abs(index)%len);

y1=getPaddingTop()+width*(index/len);
x2=x1+width;
y2=y1+width; 

有了这些点的关系,就可以通过canvas.drawRect(rect, paint);绘制出方块了

3.绘制奖品图

  //绘制奖品
  private void drawPrize(Canvas canvas) {
    int width = getMeasuredWidth()/3;
    int x1=0;
    int y1=0;

    int x2=0;
    int y2=0;

    int len = (int) Math.sqrt(prizes.size());

    for(int x=0;x<len*len;x++){

      Prize prize = prizes.get(x);

      int index=x;
      x1=getPaddingLeft()+width*(Math.abs(index)%len);
      y1=getPaddingTop()+width*(index/len);

      x2=x1+width;
      y2=y1+width;
      Rect rect=new Rect(x1+width/6,y1+width/6,x2-width/6,y2-width/6);
      prize.setRect(rect);
      canvas.drawBitmap(prize.getIcon(), null, rect, null);

    }
  }

通过了步骤1,2知道了方块的位置关系,就可以轻松的根据这些关系绘制出奖品来,Rect rect=new Rect(x1+width/6,y1+width/6,x2-width/6,y2-width/6);是让奖品比方块缩小一些,这样看起来会更自然一点。

4.计算旋转方块的下一步位置

  //下一步
  public int next(int position,int len){
    int current=position;
    if(current+1<len){
      return ++current;
    }

    if((current+1)%len==0&&current<len*len-1){
      return current+=len;
    }

    if(current%len==0){
      return current-=len;
    }

    if(current<len*len){
      return --current;
    }

    return current;
  }

position是当前旋转方块的位置,len是3

5.绘制旋转方块

  //绘制旋转的方块
  private void drawTransfer(Canvas canvas) {
    int width = getMeasuredWidth()/3;
    int x1;
    int y1;

    int x2;
    int y2;
    int len = (int) Math.sqrt(prizes.size());
    //得到下一步方块的位置
    current=next(current, len);
    x1=getPaddingLeft()+width*(Math.abs(current)%len);
    y1=getPaddingTop()+width*((current)/len);

    x2=x1+width;
    y2=y1+width;

    Rect rect=new Rect(x1,y1,x2,y2);
    Paint paint=new Paint();
    paint.setColor(transfer);
    canvas.drawRect(rect, paint);
  }

6.监听点击开始按钮事件

  private OnTransferWinningListener listener;

  public void setOnTransferWinningListener(OnTransferWinningListener listener){
    this.listener=listener;
  }

  public interface OnTransferWinningListener{
    /**
     * 中奖回调
     * @param position
     */
    void onWinning(int position);
  }
    @Override
  public boolean onTouchEvent(MotionEvent event) {
    handleTouch(event);
    return super.onTouchEvent(event);
  }
  /**
   * 触摸
   * @param event
   */
  public void handleTouch(MotionEvent event) {

    Point touchPoint=new Point((int)event.getX()-getLeft(),(int)event.getY());
    switch(event.getAction()){
    case MotionEvent.ACTION_DOWN:
      Prize prize = prizes.get(Math.round(prizes.size())/2);
      if(prize.isClick(touchPoint)){
        if(!flags){
          setStartFlags(true);
          prize.click();
        }
      }
      break ;
    default:
      break ;
    }
  }

//控制旋转
  private void controllerTransfer() {
    if(count>MAX){
      countDown++;
      SystemClock.sleep(count*5);
    }else{
      SystemClock.sleep(count*2);
    }

    count++;
    if(countDown>2){
      if(lottery==current){
        countDown=0;
        count=0;
        setStartFlags(false);

        if(listener!=null){
          //切换到主线程中运行
          post(new Runnable() {

            @Override
            public void run() {
              listener.onWinning(current);
            }
          });

        }
      }
    }
  }

至此,基本的自定义工作已经差不多了,使用demo如下:

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

  <com.example.test.LotteryView
    android:id="@+id/nl"
     android:layout_width="match_parent"
    android:layout_height="match_parent"
    />

</RelativeLayout>
public class HomeActivity extends Activity {

  LotteryView nl;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.act_home);

    nl=(LotteryView) findViewById(R.id.nl);

    int[]prizesIcon={R.drawable.danfan,R.drawable.meizi,R.drawable.iphone,R.drawable.f015,R.drawable.arrow,R.drawable.f040,R.drawable.ipad,R.drawable.spree_icon,R.drawable.spree_success_icon};
    final List<Prize>prizes=new ArrayList<Prize>();
    for(int x=0;x<9;x++){
      Prize lottery=new Prize();
      lottery.setId(x+1);
      lottery.setName("Lottery"+(x+1));
      Bitmap bitmap = BitmapFactory.decodeResource(getResources(), prizesIcon[x]);
      lottery.setIcon(bitmap);
      if((x+1)%2==0){
        lottery.setBgColor(0xff4fccee);
      }else if(x==4){
        lottery.setBgColor(0xffffffff);
      }else{
        lottery.setBgColor(0xff00ff34);
      }

      prizes.add(lottery);
    }
    nl.setPrizes(prizes);
    nl.setOnTransferWinningListener(new OnTransferWinningListener() {

      @Override
      public void onWinning(int position) {
        Toast.makeText(getApplicationContext(), prizes.get(position).getName(), Toast.LENGTH_SHORT).show();
      }
    });
  }
}

运行效果非常流畅

LotteryView整体demo:

package com.example.test;

import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuff.Mode;
import android.graphics.Rect;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;

public class LotteryView extends SurfaceView implements Callback{

 /**
 * holder
 */
 private SurfaceHolder mHolder;

 private List<Prize>prizes;
 private boolean flags;

 private int lottery=6; //设置中奖号码

 private int current=2; //抽奖开始的位置

 private int count=0; //旋转次数累计

 private int countDown; //倒计次数,快速旋转完成后,需要倒计多少次循环才停止

 private int transfer= 0xffff0000;

 private int MAX=50; //最大旋转次数

 private OnTransferWinningListener listener;

 public void setOnTransferWinningListener(OnTransferWinningListener listener){
 this.listener=listener;
 }

 public interface OnTransferWinningListener{
 /**
  * 中奖回调
  * @param position
  */
 void onWinning(int position);
 }

 /**
 * 设置中奖号码
 * @param lottery
 */
 public void setLottery(int lottery) {
 if(prizes!=null&&Math.round(prizes.size()/2)==0){
  throw new RuntimeException("开始抽奖按钮不能设置为中奖位置!");
 }
 this.lottery = lottery;
 }

 /**
 * 设置转盘颜色
 * @param transfer
 */
 public void setTransfer(int transfer) {
 this.transfer = transfer;
 }

 /**
 * 设置奖品集合
 * @param prizes
 */
 public void setPrizes(List<Prize>prizes){
 this.prizes=prizes;
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
 handleTouch(event);
 return super.onTouchEvent(event);
 }

 /**
 * 触摸
 * @param event
 */
 public void handleTouch(MotionEvent event) {

 Point touchPoint=new Point((int)event.getX()-getLeft(),(int)event.getY());
 switch(event.getAction()){
 case MotionEvent.ACTION_DOWN:
  Prize prize = prizes.get(Math.round(prizes.size())/2);
  if(prize.isClick(touchPoint)){
  if(!flags){
   setStartFlags(true);
   prize.click();
  }
  }
  break ;
 default:
  break ;
 }
 }
 private class SurfaceRunnable implements Runnable{
 @Override
 public void run() {
  while(flags){
  Canvas canvas=null;
  try {
   canvas = mHolder.lockCanvas();

   drawBg(canvas);

   drawTransfer(canvas);

   drawPrize(canvas);

   controllerTransfer();
  } catch (Exception e) {
   e.printStackTrace();
  }finally{
   //涓轰簡璁╂瘡娆$粯鍒跺浘褰㈡椂鑳藉椤哄埄杩涜锛屾渶濂藉皢瑙i攣鏀惧埌寮傚父涓繘琛屽鐞嗭紝涔熷氨鏄锛屽鏋渃anvas涓嶄负绌猴紝閮藉皢鍏跺叧闂紝璁╀笅涓�娆″惊鐜兘澶熼『鍒╄繘琛岀粯鍒�
   if(canvas!=null)
   mHolder.unlockCanvasAndPost(canvas);
  }
  }
 }
 }

 //绘制背景
 private void drawBg(Canvas canvas) {
 canvas.drawColor(Color.WHITE, Mode.CLEAR);
 int width = getMeasuredWidth()/3;
 int x1=0;
 int y1=0;

 int x2=0;
 int y2=0;

 int len = (int) Math.sqrt(prizes.size());

 for(int x=0;x<len*len;x++){

  Prize prize = prizes.get(x);

  int index=x;
  x1=getPaddingLeft()+width*(Math.abs(index)%len);
  y1=getPaddingTop()+width*(index/len);

  x2=x1+width;
  y2=y1+width;
  Rect rect=new Rect(x1,y1,x2,y2);

  Paint paint=new Paint();
  paint.setColor(prize.getBgColor());
  canvas.drawRect(rect, paint);
 }
 }

 //绘制旋转的方块
 private void drawTransfer(Canvas canvas) {
 int width = getMeasuredWidth()/3;
 int x1;
 int y1;

 int x2;
 int y2;
 int len = (int) Math.sqrt(prizes.size());
 current=next(current, len);
 x1=getPaddingLeft()+width*(Math.abs(current)%len);
 y1=getPaddingTop()+width*((current)/len);

 x2=x1+width;
 y2=y1+width;

 Rect rect=new Rect(x1,y1,x2,y2);
 Paint paint=new Paint();
 paint.setColor(transfer);
 canvas.drawRect(rect, paint);
 }

 //控制旋转
 private void controllerTransfer() {
 if(count>MAX){
  countDown++;
  SystemClock.sleep(count*5);
 }else{
  SystemClock.sleep(count*2);
 }

 count++;
 if(countDown>2){
  if(lottery==current){
  countDown=0;
  count=0;
  setStartFlags(false);

  if(listener!=null){
   //切换到主线程中运行
   post(new Runnable() {

   @Override
   public void run() {
    listener.onWinning(current);
   }
   });

  }
  }
 }
 }

 public void setStartFlags(boolean flags){
 this.flags=flags;
 }

 //绘制奖品
 private void drawPrize(Canvas canvas) {
 int width = getMeasuredWidth()/3;
 int x1=0;
 int y1=0;

 int x2=0;
 int y2=0;

 int len = (int) Math.sqrt(prizes.size());

 for(int x=0;x<len*len;x++){

  Prize prize = prizes.get(x);

  int index=x;
  x1=getPaddingLeft()+width*(Math.abs(index)%len);
  y1=getPaddingTop()+width*(index/len);

  x2=x1+width;
  y2=y1+width;
  Rect rect=new Rect(x1+width/6,y1+width/6,x2-width/6,y2-width/6);
  prize.setRect(rect);
  canvas.drawBitmap(prize.getIcon(), null, rect, null);

 }
 }

 public void start() {
 setLottery(getRandom());
 ExecutorService service = Executors.newCachedThreadPool();
 service.execute(new SurfaceRunnable());
 }

 //获取随机中奖数,实际开发中一般中奖号码是服务器告诉我们的
 private int getRandom(){
 Random r=new Random();
 int nextInt =r.nextInt(prizes.size());
 if(nextInt%(Math.round(prizes.size()/2))==0){
  //随机号码等于中间开始位置,需要继续摇随机号
  return getRandom();
 }
 return nextInt;
 }

 //下一步
 public int next(int position,int len){
 int current=position;
 if(current+1<len){
  return ++current;
 }

 if((current+1)%len==0&&current<len*len-1){
  return current+=len;
 }

 if(current%len==0){
  return current-=len;
 }

 if(current<len*len){
  return --current;
 }

 return current;
 }

 public LotteryView(Context context, AttributeSet attrs) {
 super(context, attrs);
 mHolder = this.getHolder();
 mHolder.addCallback(this);
 }

 public LotteryView(Context context) {
 this(context,null);
 }

 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int width,
  int height) {
 }

 @Override
 public void surfaceCreated(SurfaceHolder holder) {
 Canvas canvas=null;
 try {
  canvas = mHolder.lockCanvas();
  drawBg(canvas);
  drawPrize(canvas);

  Prize prize = prizes.get(Math.round(prizes.size()/2));
  prize.setListener(new Prize.OnClickListener() {

  @Override
  public void onClick() {
   start();
  }
  });
 } catch (Exception e) {
  e.printStackTrace();
 }finally{
  if(canvas!=null)
  mHolder.unlockCanvasAndPost(canvas);
 }
 }

 @Override
 public void surfaceDestroyed(SurfaceHolder holder) {
 setStartFlags(false);
 }

 /**
 * 重新测量
 */
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
 {
 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 int width = Math.min(getMeasuredWidth(), getMeasuredHeight());
 setMeasuredDimension(width, width);
 }
}

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

(0)

相关推荐

  • Android中利用SurfaceView制作抽奖转盘的全流程攻略

    一.概述 今天给大家带来SurfaceView的一个实战案例,话说自定义View也是各种写,一直没有写过SurfaceView,这个玩意是什么东西?什么时候用比较好呢? 可以看到SurfaceView也是继承了View,但是我们并不需要去实现它的draw方法来绘制自己,为什么呢? 因为它和View有一个很大的区别,View在UI线程去更新自己:而SurfaceView则在一个子线程中去更新自己:这也显示出了它的优势,当制作游戏等需要不断刷新View时,因为是在子线程,避免了对UI线程的阻塞. 知

  • Android App中实现简单的刮刮卡抽奖效果的实例详解

    主要思想: 将一个view设计成多层:背景层,含中奖信息等: 遮盖层,用于刮奖,使用关联一个Bitmap的Canvas 在该Bitmap上,使用它的canvas.drawPath的api来处理 手势滑动(类似刮奖的动作) 使用paint.setXfermode 来进行消除手势滑动区域 public class GuaView extends View { private Bitmap mBitmap; //遮盖的图层 private Canvas mCanvas; //绘制遮盖图层 privat

  • js和html5实现手机端刮刮卡抽奖效果完美兼容android/IOS

    绝对值得看的来篇,哈哈.本人亲自完成,有错误请大家指出: 现在的手机完美支持html5,所以如果手机端想要做个抽奖模块的话,用刮刮卡抽奖效果,相信这个互动体验是非常棒的 ​ps:由于本人没有wp8系统的手机,所以没法兼容wp8系统的,目前完美兼容android,IOS 如果要在pc浏览的话,得改下js,目前支持谷歌,火狐,ie>=10,如果网友想要的话我就去写个 代码如下: 复制代码 代码如下: <!DOCTYPE html> <html lang="en"&g

  • Android抽奖轮盘的制作方法

    本文实例为大家分享了Android抽奖轮盘的具体代码,供大家参考,具体内容如下 main布局(图片资源请自行寻找,抱歉) <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gra

  • Android使用surfaceView自定义抽奖大转盘

    使用surfaceView自定义抽奖大转盘 话不多说,先上效果图 完整代码地址欢迎start 实现思路以及过程 1.首先了解SurfaceView的基本用法,它跟一般的View不太一样,采用的双缓存机制,可以在子线程中绘制View,不会因为绘制耗时而失去流畅性,这也是选择使用SurfaceView去自定义这个抽奖大转盘的原因,毕竟绘制这个转盘的盘块,奖项的图片和文字以及转动都是靠绘制出来的,是一个比较耗时的绘制过程. 2.使用SurfaceView的一般模板样式 一般会用到的成员变量 priva

  • Android简单实现圆盘抽奖界面

    闲来无事,做了一个简单的抽奖转盘的ui实现,供大家参考 package com.microchange.lucky; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet;

  • Android自定义View实现QQ运动积分转盘抽奖功能

    因为偶尔关注QQ运动, 看到QQ运动的积分抽奖界面比较有意思,所以就尝试用自定义View实现了下,原本想通过开发者选项查看下界面的一些信息,后来发现积分抽奖界面是在WebView中展示的,应该是在H5页面中用js代码实现的,暂时不去管它了. 这里的自定义View针对的是继承自View的情况,你可以将Canvas想象为画板, Paint为画笔,自定义View的过程和在画板上用画笔作画其实类似,想象在画板上作画的过程,你要画一个多大图形(对应View的测量 onMeasure方法),你要画什么样的图

  • Android实现抽奖转盘实例代码

    本文详述了android抽奖程序的实现方法,程序为一个抽奖大转盘代码,里面定义了很多图形方法和动画. 实现主要功能的SlyderView.java源代码如下: import android.app.Activity; import android.content.Context; import android.graphics.BlurMaskFilter; import android.graphics.Canvas; import android.graphics.Color; import

  • Android打造流畅九宫格抽奖活动效果

    因为company项目中需要做九宫格抽奖活动,以前都没有做过类似的功能,虽然之前在浏览大神们的博客中,无意中也看到了好多关于抽奖的项目,但因为项目中没有需要,一直都没有点击进去看.这次不去看估计不行.直到公司计划要做抽奖功能,才迫不得已上网查找demo 网上找了大半天,好不容易找到了几个demo,下载下来,解压缩包发现竟然里面空空如也,只有几张九宫格的图片,害我白白浪费了几个CSDN积分.后面在eoe网站那发现了一个demo,于是好开心,下载下来后马上导入到工程中,运行看了效果,九宫格是出来了,

  • 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

  • Android实现LED发光字效果

    大家好,这一篇博客来教大家一个类似于LED闹钟显示屏样式的小案例,UI比较美观,文末会提供下载相关资源地址供大家下载,首先我们来看一看这个案例的运行效果. 正常运行在手机中时,效果很流畅,gif上可能是由于录制完转码的时候,速度调快了,所以看上去速度比较快,这都是小事情,接下来我们来看看源码是如何实现的. 1.代码很简单,主要是利用xml布局文件的几个属性,并且通过设置我们特定的字体就能很容易的实现我们看到的效果啦,首先我们创建一个类LedTextView继承自TextView. public

  • Android自定义控件实现九宫格解锁功能

    最终Android九宫格解锁效果如下 1.进行定义实体point点 public class Point { private float x; private float y; //正常模式 public static final int NORMAL_MODE = 1; //按下模式 public static final int PRESSED_MODE = 2; //错误模式 public static final int ERROR_MODE = 3; private int state

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

    不知道大家有没有用过,淘宝电影客户端(淘票票)买过电影票,纵观各类在线选座app的在线选座功能 淘宝在线选座功能用户体验最好,用起来最顺手,夸张点说已经到了炉火纯青的地步,下面我们看一下效果: 效果分析: 整个控件分成几个部分,座位图区域.座位缩略图区域.行号区域.屏幕区域 1.座位图可以自由的移动缩放,放大缩小移动后会自动回弹到合适的位置,选中座位会自动放大到合适比例. 2.行号部分跟着座位图缩放以及上下移动,屏幕区域跟着座位图左右移动缩放. 3.当手指按下的时候会出现缩略图,缩略图上有个红色

  • Android 实现数字九宫格软键盘

    前言 一开始大概是这种 需求 组长说 要不搞一个自定义软键盘吧 数字搞大点 方便外卖员输入数字 我设置了输入EditText的输入格式为Number 还是不行 那就开搞吧 先来看下实现的效果图吧 实现效果GIF 实现代码 自定义View 一个NineNumericKeyboardView /** * Author by Lyu * Date on 2021/5/26-19:55 * Description:九宫格数字软键盘 */ public class NineNumericKeyboardV

  • Android实现图片九宫格

    本文实例为大家分享了Android实现图片九宫格的具体代码,供大家参考,具体内容如下 九宫格分三类 实现的效果 具体实现 activity_main <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.

  • Android仿微信底部菜单栏效果

    前言 在市面上,大多数的APP都需要通过底部菜单栏来将程序的功能进行分类整理,通常都是分为3-5个大模块,从而正确有效地引导用户去使用我们的APP.实现底部菜单栏的方法也有很多种. 1.仿微信底部菜单栏(ViewPager+ImagerView+TextView) ......(其他方式后续会补充) 效果预览 首先来个开胃菜,看看实现效果: 先贴出项目所需的资源文件,这些可随个人自由更改颜色和文字 colors.xml <color name="bg_line_light_gray&quo

  • Android基于TextView属性android:ellipsize实现跑马灯效果的方法

    本文实例讲述了Android基于TextView属性android:ellipsize实现跑马灯效果的方法.分享给大家供大家参考,具体如下: Android系统中TextView实现跑马灯效果,必须具备以下几个条件: 1.android:ellipsize="marquee" 2.TextView必须单行显示,即内容必须超出TextView大小 3.TextView要获得焦点才能滚动 XML代码: android:ellipsize="marquee", andro

  • Android实现自定义的弹幕效果

    一.效果图 先来看看效果图吧~~ 二.实现原理方案 1.自定义ViewGroup-XCDanmuView,继承RelativeLayout来实现,当然也可以继承其他三大布局类哈 2.初始化若干个TextView(弹幕的item View,这里以TextView 为例,当然也可以其他了~),然后通过addView添加到自定义View中 3.通过addView添加到XCDanmuView中,位置在坐标,为了实现 从屏幕外移动进来的效果 我们还需要修改添加进来TextView的位置,以从右向左移动方向

随机推荐