国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android打造流暢九宮格抽獎活動效果

2019-12-12 04:46:46
字體:
來源:轉載
供稿:網友

因為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&¤t<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{   //涓轟

主站蜘蛛池模板:
靖州|
恩施市|
博乐市|
南江县|
商都县|
泊头市|
永昌县|
衡南县|
渭源县|
华容县|
开封县|
南川市|
富川|
玉溪市|
岗巴县|
新蔡县|
大竹县|
胶南市|
汤原县|
泰兴市|
卢氏县|
蒲江县|
三原县|
麦盖提县|
江源县|
井研县|
莱阳市|
陇西县|
商河县|
丰镇市|
宝山区|
华安县|
黔南|
五家渠市|
裕民县|
盱眙县|
安吉县|
东平县|
奎屯市|
筠连县|
卫辉市|