欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android拼图游戏 玩转从基础到应用手势变化

程序员文章站 2024-03-04 11:38:35
相信大家在小的时候都玩过拼图游戏,现如今,手机普及,能在手机上玩的游戏越来越多,于是乎,重温小时候,编写这个简易拼图游戏,而且也能进一步加深android的一些基础知识。...

相信大家在小的时候都玩过拼图游戏,现如今,手机普及,能在手机上玩的游戏越来越多,于是乎,重温小时候,编写这个简易拼图游戏,而且也能进一步加深android的一些基础知识。
老规矩,先是效果图:

Android拼图游戏 玩转从基础到应用手势变化

这里我把为了演示效果,把图片打乱的很少,在代码里可以更改。

首先,有个默认的图片,可以用来拼图,也可以选择你喜欢的图片进行拼图,拼图的过程会记录移动的步数,并且当游戏胜利的时候会弹出一个笑脸提示,游戏胜利,用了多少步数。

ps:感兴趣的完全可以继续在这上面进行扩展,比如增加游戏难度的选项,可以将图片分成更多的小方块等等。

大体思路:将大图切割成各个小方块,用数组记录每个小方块的信息,用gridlayout来显示各个小方块,并且将某个小方块标记为空白方块(空白方块可以和相邻方块进行交换),在gridlayout上的各个小方块上增加点击事件和在整个屏幕上添加手势事件,每次点击或者有手势时,判断小方块是否能移动,最后在游戏胜利时弹出胜利提示。
话不多说,接下来,就是一步步实现拼图游戏的过程啦。

1.小方块相关的类。

这是小方块的各种变量的item,类,用来管理将大图切割成每个小方块的每个小方块的信息。很简单,就是各种变量和setter和getter方法直接上代码~

/**
 * created by yyh on 2016/10/21.
 */
public class gameitemview{
  /**
   * 每个小方块的信息
   */
  //每个小方块的实际位置x,
  private int x=0;
  //每个小方块的实际位置y,
  private int y=0;
  //每个小方块的图片,
  private bitmap bm;
  //每个小方块的图片位置x,
  private int p_x=0;
  //每个小方块的图片位置y.
  private int p_y=0;
  public gameitemview(int x, int y, bitmap bm) {
    super();
    this.x = x;
    this.y = y;
    this.bm = bm;
    this.p_x=x;
    this.p_y=y;
  }
  public int getx() {
    return x;
  }
  public void setx(int x) {
    this.x = x;
  }
  public int gety() {
    return y;
  }

  public bitmap getbm() {
    return bm;
  }

  public void setbm(bitmap bm) {
    this.bm = bm;
  }

  public int getp_x() {
    return p_x;
  }

  public void setp_x(int p_x) {
    this.p_x = p_x;
  }

  public int getp_y() {
    return p_y;
  }

  public void setp_y(int p_y) {
    this.p_y = p_y;
  }
  /**
   * 判断每个小方块的位置是否正确
   * @return
   */
  public boolean istrue(){
    if (x==p_x&&y==p_y){
      return true;
    }
    return false;
  }
}

2.主界面的布局

主界面很简单,一个button,用来换图片,一个imageview,用来显示原图,一个gridlayout用来进行拼图游戏,最后,一个textview,用来显示完成这个拼图用了多少步数。布局如下:

<?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"
  >
  <linearlayout
    android:id="@+id/ll"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    >
    <button
      android:id="@+id/bt_choice"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="选择图片"
      android:adjustviewbounds="true"
      />

  </linearlayout>

  <imageview
    android:id="@+id/iv"
    android:layout_below="@id/ll"
    android:adjustviewbounds="true"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/haizei"
    android:layout_margintop="3dp"
    ></imageview>

  <!-- 游戏的主界面-->
  <gridlayout
    android:layout_margintop="3dp"
    android:layout_below="@id/iv"
    android:id="@+id/gl"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:columncount="5"
    android:rowcount="3"
    android:adjustviewbounds="true"
    >
  </gridlayout>
  <textview
    android:id="@+id/tv_step"
    android:layout_below="@id/gl"
    android:layout_margintop="3dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="已用步数:0"
    android:textsize="26sp"
    />

</relativelayout>

3.打开图片选择图片

给button设置点击事件,调用startactivityforresult(intent intent,int requestcode);方法,来获取图片。

 bt_choice.setonclicklistener(new view.onclicklistener() {
      @override
      public void onclick(view v) {
        intent intent= new intent("android.intent.action.get_content");
        intent.settype("image/*");
        startactivityforresult(intent, choice_photo);//打开相册
      }
    });

在activity中重写onactivityresult(int requestcode, int resultcode, intent data)方法来显示选择的图片,以及初始化游戏。(图片选择完以后,就要进行图片的切割,和拼图游戏的开始。)

 protected void onactivityresult(int requestcode, int resultcode, intent data) {
    super.onactivityresult(requestcode, resultcode, data);
    switch (requestcode){
      case choice_photo:
        if (resultcode==result_ok){
          //判断手机系统版本
          if (build.version.sdk_int>=19){
            handleimageonkitkat(data);
            //得到imageview中的图片
            bitmapdrawable bitmapdrawable= (bitmapdrawable) photo.getdrawable();
            bt_tupan=bitmapdrawable.getbitmap();
            //将原来gridlayout中的小方块移除,
            removegameitem();
            //将新图切割成小方块并加入gridlayout.
            setgameitem();
            //开始游戏
            startgame();
          }else {
            handleimagebeforekitkat(data);
            //得到imageview中的图片
            bitmapdrawable bitmapdrawable= (bitmapdrawable) photo.getdrawable();
            bt_tupan=bitmapdrawable.getbitmap();
             //将原来gridlayout中的小方块移除,
            removegameitem();
            //将新图切割成小方块并加入gridlayout.
            setgameitem();
            //开始游戏
            startgame();
          }
        }
    }
  }

然后是选择图片的具体方法的实现函数。注释很清楚,不多说。我们的重点在拼图以及手势变化的具体实现,这里选择图片的方式很多。不多讲,网上有现成的框架。

 //手机不大于19的取数据方法
  private void handleimagebeforekitkat(intent data) {
    uri uri =data.getdata();
    string imagepath = getimagepath(uri, null);
    displayimage(imagepath);
  }
  /**
   * 手机大于19的取数据方法
   * @param data
   */
  @targetapi(build.version_codes.kitkat)
  private void handleimageonkitkat(intent data) {
    string imagepath=null;
    uri uri=data.getdata();
    if (documentscontract.isdocumenturi(this,uri)){
      //如果是document类型的url,则通过document的id处理。
      string docid=documentscontract.getdocumentid(uri);
      if ("com.android.providers.media.documents".equals(uri.getauthority())){
        string id =docid.split(":")[1];//解析出数字格式的id;
        string selection= mediastore.images.media._id+"="+id;
        imagepath=getimagepath(mediastore.images.media.external_content_uri,selection);
      }else if ("com.android.providers.downloads.documents".equals(uri.getauthority())){
        uri contenturi= contenturis.withappendedid(uri.parse("content://downloads/public_downloads"),long.valueof(docid));
        imagepath=getimagepath(contenturi,null);
      }
    }else if ("content".equalsignorecase(uri.getscheme())){
      //如果不是document类型的uri,则使用普通的方式处理。
      imagepath=getimagepath(uri,null);
    }
    displayimage(imagepath);
  }
  /**
   * 显示图片
   * @param imagepath //图片的路径。
   */
  private void displayimage(string imagepath) {
    if (imagepath != null) {
      bitmap bitmap = bitmapfactory.decodefile(imagepath);
      if (isheigthbigwidth(bitmap)) {
        bitmap bt = rotaingimageview(bitmap);//将图片旋转90度。
        bitmap disbitmapt = ajustbitmap(bt);
        photo.setimagebitmap(disbitmapt);
      } else {
        bitmap disbitmap = ajustbitmap(bitmap);
        photo.setimagebitmap(disbitmap);
      }
    }
  }

  /**
   * 调整图片的方向
   * @param bitmap
   * @return
   */
  private bitmap rotaingimageview(bitmap bitmap) {
    //旋转图片 动作
    matrix matrix = new matrix();;
    matrix.postrotate(270);
    // 创建新的图片
    bitmap resizedbitmap = bitmap.createbitmap(bitmap, 0, 0,
        bitmap.getwidth(), bitmap.getheight(), matrix, true);
    return resizedbitmap;
  }
  /**
   * 得到图片的路径
   * @param externalcontenturi
   * @param selection
   * @return
   */
  private string getimagepath(uri externalcontenturi, string selection) {
    string path=null;
    cursor cursor=getcontentresolver().query(externalcontenturi, null, selection, null, null);
    if (cursor!=null){
      if (cursor.movetofirst()){
        path=cursor.getstring(cursor.getcolumnindex(mediastore.images.media.data));
      }
    }
    cursor.close();
    return path;
  }

4.拼图的各个小方块的形成过程。

看着各个小方块,我们用gridlayout来实现是最为方便的。所以,用一个gridlayout来显示大图切割后的各个小方块,用一个imageview数组来保存各个小方块的信息,并且,我们默认把最后一个小方块设置为空白方块。

首先是各种需要的变量。注释很清楚。

 /**
   * 利用二维数组创建若干个游戏小方框
   */
  private imageview [][] iv_game_arr=new imageview[3][5];
  /**
   *游戏主界面
   *
   */
  private gridlayout gl_game_layout;
  //小方块的行和列
  private int i;
  private int j;
  /**空方块的全局变量*/
  private imageview iv_null_imagview;

接着是从imageview获取图片,并且将图片按照一定的行和列进行切割(这里将拼图设置为3行5列)。将切割后的各个小方块的信息保存在一个imageview数组中。给每个小方块设置tag,和点击监听。

 private void setgameitem() {
    //调整图片的尺寸
    bitmap abitmap=ajustbitmap(bt_tupan);
    int ivwidth=getwindowmanager().getdefaultdisplay().getwidth()/5;//每个游戏小方块的宽和高。切成正方形
    int tuwidth=abitmap.getwidth()/5; 
    for (int i=0;i<iv_game_arr.length;i++){
      for (int j=0;j<iv_game_arr[0].length;j++){
        //将大图切成小方块
        bitmap bm=bitmap.createbitmap(abitmap,j*tuwidth,i*tuwidth,tuwidth,tuwidth);
        iv_game_arr[i][j]=new imageview(this);
        iv_game_arr[i][j].setimagebitmap(bm);//设置每一个小方块的图案
        iv_game_arr[i][j].setlayoutparams(new relativelayout.layoutparams(ivwidth, ivwidth));
        //设置方块之间的间距
        iv_game_arr[i][j].setpadding(2, 2, 2, 2);
        iv_game_arr[i][j].settag(new gameitemview(i, j, bm)); //绑定自定义数据
        iv_game_arr[i][j].setonclicklistener(new view.onclicklistener() {
        .......

);

当然,我们选择的图片不可能都是符合标准的大小的,所以,在切割图片之前我们要对图片进行调整。将图片调整为5:3的比例。(这样切割成3行5列的小方块才能正确切割)这里对于width,我把每个小方块的间隔事先也算到里面去。

 //调整图片的大小
  private bitmap ajustbitmap(bitmap bitmap) {
    int width=getwindowmanager().getdefaultdisplay().getwidth()-(iv_game_arr[0].length-1)*2;
    int heigth=width/5*3;
    bitmap scaledbitmap=bitmap.createscaledbitmap(bitmap, width, heigth, true);
    return scaledbitmap;
  }

将每个小方格放入到gridlayout中。

 /**
   * 将小方格放入gridlayout
   */
  private void startgame() {
    tv_step.settext("已用步数:0");
    for (i = 0; i <iv_game_arr.length; i++){
      for (j = 0; j <iv_game_arr[0].length; j++){
        gl_game_layout.addview(iv_game_arr[i][j]);
      }
    }
    //将最后一个方块设置为设置空方块。
    setnullimageview(iv_game_arr[i-1][j-1]);

5.小方块的点击事件和手势判断过程。

这里是拼图游戏的核心,弄懂了小方块的移动变化规律,也就弄懂了拼图游戏。

对于点击事件,首先拿到被点击的小方块的各种信息(位置、图案)和空白小方块的位置信息,判断被点击的小方块是否和空白小方块相邻,如果相邻,就移动交换数据(用translateanimation来实现移动动画),如果不相邻则无操作。
a.判断点击方块和空白方块是否相邻的方法

/**
   *  判断当前点击的方块,是否和空方块相邻。
   * @param imageview 当前点击的方块
   * @return true:相邻。 false:不相邻。
   */
  public boolean isadjacentnullimageview(imageview imageview){
    //获取当前空方块的位置与点击方块的位置
    gameitemview null_gameitemview= (gameitemview) iv_null_imagview.gettag();
    gameitemview now_gameitem_view = (gameitemview) imageview.gettag();
   if(null_gameitemview.gety()==now_gameitem_view.gety()&&now_gameitem_view.getx()+1==null_gameitemview.getx()){//当前点击的方块在空方块的上面
      return true;
    }else if(null_gameitemview.gety()==now_gameitem_view.gety()&&now_gameitem_view.getx()==null_gameitemview.getx()+1){//当前点击的方块在空方块的下面
      return true;
    }else if(null_gameitemview.gety()==now_gameitem_view.gety()+1&&now_gameitem_view.getx()==null_gameitemview.getx()){//当前点击的方块在空方块的左面
      return true;
    }else if(null_gameitemview.gety()+1==now_gameitem_view.gety()&&now_gameitem_view.getx()==null_gameitemview.getx()){ ////当前点击的方块在空方块的右面
      return true;
    }
    return false;
  }

b.接着是如果相邻就进入方块数据交换的方法
这里有个方法重载,是否需要动画效果,没有动画效果的数据交换是为初始化游戏时打乱拼图做准备的。这里将核心交换代码列出。每次交换后还要判断是否游戏胜利(即是否拼图完成~)。

    //得到点击方块绑定的数据
      gameitemview gameitemview = (gameitemview) itemimageview.gettag();
      //将空方块的图案设置为点击方块
      iv_null_imagview.setimagebitmap(gameitemview.getbm());
      //得到空方块绑定的数据
      gameitemview null_gameitemview = (gameitemview) iv_null_imagview.gettag();
      //交换数据(将点击方块的数据传入空方块)
      null_gameitemview.setbm(gameitemview.getbm());
      null_gameitemview.setp_x(gameitemview.getp_x());
      null_gameitemview.setp_y(gameitemview.getp_y());
      //设置当前点击的方块为空方块。
      setnullimageview(itemimageview);
      if (isstart){
        isgamewin();//成功时,会弹一个吐司。
      }

c.交换时的动画设置
交换设置动画时,首先判断移动的方向,根据方向设置不同的移动动画,然后再监听动画完成后,进行数据交换操作。即上面b.接着是如果相邻就进入方块数据交换的方法.最后执行动画。

 //1.创建一个动画,设置方向,移动的距离
//判断方向,设置动画
    if (itemimageview.getx()>iv_null_imagview.getx()){//当前点击的方块在空方块的上面
      //下移
      translateanimation = new translateanimation(0.1f,-itemimageview.getwidth(),0.1f,0.1f);
    }else if (itemimageview.getx()<iv_null_imagview.getx()){//当前点击的方块在空方块的下面
      //上移
      boolean f=itemimageview.getx()<iv_null_imagview.getx();
      //log.i("点击方块","sssssssssssssssssssssssss"+f);
      translateanimation = new translateanimation(0.1f,itemimageview.getwidth(),0.1f,0.1f);
    }else if (itemimageview.gety()>iv_null_imagview.gety()){//当前点击的方块在空方块的左面
      //右移
      translateanimation=new translateanimation(0.1f,0.1f,0.1f,-itemimageview.getwidth());
    }else if(itemimageview.gety()<iv_null_imagview.gety()){//当前点击的方块在空方块的右面
      //左移
      translateanimation=new translateanimation(0.1f,0.1f,0.1f,itemimageview.getwidth());
    }
    //2.设置动画的各种参数
    translateanimation.setduration(80);
    translateanimation.setfillafter(true);
    //3.设置动画的监听
    translateanimation.setanimationlistener(new animation.animationlistener() {
      @override
      public void onanimationstart(animation animation) {
        isaminmove=true;
      }
      @override
      public void onanimationend(animation animation) {
        //动画结束,交换数据
        ......
      }

 //动画执行
    itemimageview.startanimation(translateanimation);

点击事件的流程就完了,接下来是手势判断的事件。即不仅可以通过点击小方块进行移动,也可以通过手势移动小方块。

one.创建手势对象
在onfling方法中完成手势相关的操作。

 //创建手势对象
    gesturedetector =new gesturedetector(this, new gesturedetector.ongesturelistener() {
      @override
      public boolean ondown(motionevent e) {
        return false;
      }
      @override
      public void onshowpress(motionevent e) {
      }
      @override
      public boolean onsingletapup(motionevent e) {
        return false;
      }
      @override
      public boolean onscroll(motionevent e1, motionevent e2, float distancex, float distancey) {
        return false;
      }
      @override
      public void onlongpress(motionevent e) {
      }
      @override
      public boolean onfling(motionevent e1, motionevent e2, float velocityx, float velocityy) {
      //手势相关的操作
      ......
  }

接着我们onfling方法中做具体操作

two.判断手势移动的方向
根据返回值的不同得到不同的移动方向。

 /**
   * 增加手势滑动,根据手势判断是上下左右滑动
   * @param start_x 手势起始点x
   * @param start_y 手势起始点y
   * @param end_x 手势终止点 x
   * @param end_y 手势终止点y
   * @return 1:上 2:下 3:左 4:右
   */
  public int getdirctionbygesure(float start_x,float start_y,float end_x,float end_y){
    boolean isleftorright =(math.abs(end_x-start_x)>math.abs(end_y-start_y))?true:false; //是否是左右
    if(isleftorright){//左右
      boolean isleft=(end_x-start_x)>0?false:true;
      if(isleft){
        return 3;
      }else {
        return 4;
      }
    }else{//上下
      boolean isup=(end_y-start_y)>0?false:true;
      if (isup){
        return 1;
      }else {
        return 2;
      }
    }
  }

three.根据空方块和移动的方向,判断能否移动以及进行移动操作。
因为是手势,移动的肯定是空方块周围的方块,所以重点就是要判断空方块在要移动的方块的那个方向,再根据方向判断能否移动,进行移动操作。(其中changedatebyimageview()中的方法就是具体的方块交换数据及移动的操作。就是点击事件的那个方法。)

/**重载changebydirges(int type)方法;
   * 根据手势的方向,对空方块相邻位置的方块进行移动。
   * @param type 方向的返回值 1:上 2:下 3:左 5:右
   * @param isanim 是否有动画 true:有动画,false:无动画
   */
  public void changebydirges(int type,boolean isanim){
    //1.获取当前空方块的位置。
    gameitemview null_gameitemview= (gameitemview) iv_null_imagview.gettag();
    int new_x=null_gameitemview.getx();
    int new_y=null_gameitemview.gety();
    //2.根据方向,设置相应相邻的位置坐标。
    if (type==1){//说明空方块在要移动的方块的上面。
      new_x++;
    }else if (type==2){//空方块在要移动的方块的下面
      new_x--;
    }else if (type==3){//空方块在要移动的方块的左面
      new_y++;
    }else if (type==4){//空方块在要移动的方块的右面
      new_y--;
    }
    //3.判断这个新坐标是否存在
    if(new_x>=0&&new_x<iv_game_arr.length&&new_y>=0&&new_y<iv_game_arr[0].length){
      //存在,可以移动交换数据
      if(isanim){//有动画
        changedatebyimageview(iv_game_arr[new_x][new_y]);
      }else{
        changedatebyimageview(iv_game_arr[new_x][new_y],isanim);
      }
    }else{
      //什么也不做
    }
  }

好了,手势事件也就大功告成了~

当然这里有两个要注意的地方。1.首先要对当前的activity设置ontouchevent()方法,将ontouch事件交由手势去处理,其次也要设置dispatchtouchevent()方法,在里面也要向下分发给手势事件,如果不设置向下分发给手势判断,那么在gridlayout里,就只能触发点击事件而手势事件就不会起作用了。2.要增加一个是否在移动过程中的flag,如果在移动过程中,就什么也不做,要不然每次点击小方块即使在移动过程中,也会触发点击事件从而又进行动画移动,造成不好的用户体验。

 @override
  public boolean ontouchevent(motionevent event) {
    return gesturedetector.ontouchevent(event);
  }
  @override
  public boolean dispatchtouchevent(motionevent ev) {
    gesturedetector.ontouchevent(ev);
    return super.dispatchtouchevent(ev);
  }

6.游戏开始打乱方块以及游戏结束时弹出toast提示的方法。

代码很简单,直接上代码,其中,弹出的toast是一个带有自定义view动画的toast.

 //随机打乱图片的顺序
  public void randomorder(){
    //打乱的次数,为了测试方便,设置很小。
    for (int i=0;i<5;i++){
      //根据手势,交换数据,无动画。
      int type = (int) (math.random()*4)+1;
      // log.i("sssssssssfdfdfd","交换次数"+i+"type的值"+type);
      changebydirges(type, false);
    }
  }
  /**
   * 判断游戏结束的方法
   */
  public void isgamewin(){
    //游戏胜利标志
    boolean isgamewin =true;
    //遍历每个小方块
    for (i = 0; i <iv_game_arr.length; i++){
      for (j = 0; j <iv_game_arr[0].length; j++){
        //为空的方块不判断 跳过
        if (iv_game_arr[i][j]==iv_null_imagview){
          continue;
        }
        gameitemview gameitemview= (gameitemview) iv_game_arr[i][j].gettag();
        if (!gameitemview.istrue()){
          isgamewin=false;
          //跳出内层循环
          break;
        }
      }
      if (!isgamewin){
        //跳出外层循环
        break;
      }
    }
    //根据一个开关变量觉得游戏是否结束,结束时给提示。
    if (isgamewin){
      // toast.maketext(this,"游戏胜利",toast.length_short).show();
      toastutil.maketext(this,"恭喜你,游戏胜利,用了"+step+"步",toastutil.length_short,toastutil.success);
      step=0;

    }
  }

好了,重要的部分都已经完了,这里还有个自定义view的toast,关于toast的详解,将在下篇文章,这里先简单说明下自定义toast的实现过程。
首先,新建一个successtoast类,(笑脸包括左眼,有眼,笑脸弧)。我们将核心的过程给出。利用动画,实现动态笑脸画制过程。

 @override
  protected void ondraw(canvas canvas) {
    super.ondraw(canvas);
    mpaint.setstyle(paint.style.stroke);
    //话笑脸弧
    canvas.drawarc(rectf, 180, endangle, false, mpaint);
    mpaint.setstyle(paint.style.fill);
    if (issmileleft) {
    //如果是左眼,画左眼
      canvas.drawcircle(mpadding + meyewidth + meyewidth / 2, mwidth / 3, meyewidth, mpaint);
    }
    if (issmileright) {
    //如果是有眼,画右眼。
      canvas.drawcircle(mwidth - mpadding - meyewidth - meyewidth / 2, mwidth / 3, meyewidth, mpaint);
    }
  }

 /**
   * 开始动画的方法
   * @param startf 起始值
   * @param endf  结束值
   * @param time 动画的时间
   * @return
   */
  private valueanimator startviewanim(float startf, final float endf, long time) {
    //设置valueanimator 的起始值和结束值。
    valueanimator = valueanimator.offloat(startf, endf);
    //设置动画时间
    valueanimator.setduration(time);
    //设置补间器。控制动画的变化速率
    valueanimator.setinterpolator(new linearinterpolator());
    //设置监听器。监听动画值的变化,做出相应方式。
    valueanimator.addupdatelistener(new valueanimator.animatorupdatelistener() {
      @override
      public void onanimationupdate(valueanimator valueanimator) {

        manimatedvalue = (float) valueanimator.getanimatedvalue();
        //如果value的值小于0.5
        if (manimatedvalue < 0.5) {
          issmileleft = false;
          issmileright = false;
          endangle = -360 * (manimatedvalue);
          //如果value的值在0.55和0.7之间
        } else if (manimatedvalue > 0.55 && manimatedvalue < 0.7) {
          endangle = -180;
          issmileleft = true;
          issmileright = false;
          //其他
        } else {
          endangle = -180;
          issmileleft = true;
          issmileright = true;
        }
        //重绘
        postinvalidate();
      }
    });

    if (!valueanimator.isrunning()) {
      valueanimator.start();
    }
    return valueanimator;
  }

然后新建一个success_toast_layout.xml,完成toast的布局。布局是左右(左边笑脸view,右边textview的提示。)

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/root_layout"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:background="#00000000"
  android:orientation="vertical">
  <linearlayout
    android:id="@+id/base_layout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginbottom="25dp"
    android:layout_marginleft="30dp"
    android:layout_marginright="30dp"
    android:layout_margintop="25dp"
    android:background="@drawable/background_toast"
    android:orientation="horizontal">
    <linearlayout
      android:id="@+id/linearlayout"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:gravity="center">
      <com.example.yyh.puzzlepicture.activity.util.successtoast
        android:id="@+id/successview"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_gravity="center_vertical|left"
        android:layout_margin="10px"
        android:gravity="center_vertical|left" />
    </linearlayout>
    <textview
      android:id="@+id/toastmessage"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:gravity="center_vertical"
      android:padding="10dp"
      android:text="new text" />
  </linearlayout>
</linearlayout>

最后新建一个toastutil类,管理自定义的toast.

/**
 * created by yyh on 2016/10/25.
 */
public class toastutil {
  public static final int length_short = 0;
  public static final int length_long = 1;

  public static final int success = 1;


  static successtoast successtoastview;


  public static void maketext(context context, string msg, int length, int type) {
    toast toast = new toast(context);
    switch (type) {
      case 1: {
        view layout = layoutinflater.from(context).inflate(r.layout.success_toast_layout, null, false);
        textview text = (textview) layout.findviewbyid(r.id.toastmessage);
        text.settext(msg);
        successtoastview = (successtoast) layout.findviewbyid(r.id.successview);
        successtoastview.startanim();
        text.setbackgroundresource(r.drawable.success_toast);
        text.settextcolor(color.parsecolor("#ffffff"));
        toast.setview(layout);
        break;
      }

    }
    toast.setduration(length);
    toast.show();
  }

}

这样就可以在maniactivity中调用这个自定义toast了。
好了,完结。

游戏源码:拼图游戏的实现过程
github:拼图游戏

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