안 드 로 이 드 퍼 즐 게임 은 기본 에서 응용 제스처 로 변화 합 니 다.

모두 가 어 렸 을 때 퍼 즐 게임 을 한 적 이 있다 고 믿 습 니 다.지금 은 핸드폰 이 보급 되 고 핸드폰 에서 할 수 있 는 게임 이 점점 많아 지고 있 습 니 다.그래서 어 렸 을 때 이 간단 한 퍼 즐 게임 을 작 성 했 고 안 드 로 이 드 의 기초 지식 도 더욱 깊이 있 게 할 수 있 습 니 다.
낡은 규칙,먼저 효과 도:

여기 서 나 는 효 과 를 보 여주 기 위해 그림 을 거의 흐 트 러 뜨리 지 않 고 코드 에서 변경 할 수 있다.
먼저,기본 적 인 그림 이 있 습 니 다.퍼 즐 을 맞 출 수도 있 고 좋아 하 는 그림 을 선택 하여 퍼 즐 을 맞 출 수도 있 습 니 다.퍼 즐 을 맞 추 는 과정 에서 이동 하 는 걸음 수 를 기록 할 수 있 습 니 다.그리고 게임 이 승리 할 때 웃 는 얼굴 알림 이 나 옵 니 다.게임 이 승리 하고 몇 걸음 을 썼 는 지 알려 줍 니 다.
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 에 클릭 이 벤트 를 설정 하고 startActivity ForResult(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 에 onActivity Result(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.퍼 즐 의 각 작은 사각형 의 형성 과정.
각 작은 사각형 을 보면 서 우 리 는 Grid Layout 으로 실현 하 는 것 이 가장 편리 하 다.따라서 큰 그림 을 자 른 각 작은 사각형 을 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 배열 에 저장 합 니 다.각 작은 사각형 에 태 그 를 설정 하고 감청 을 클릭 합 니 다.

 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;
  }
모든 작은 칸 을 Grid Layout 에 넣 습 니 다.

 /**
   *       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) {
      //       
      ......
  }
이어서 저희 온 플 링 방법 에서 구체 적 인 조작 을 하도록 하 겠 습 니 다.
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 에 onTouch Event()방법 을 설정 하고 onTouch 사건 을 제스처 로 처리 해 야 합 니 다.그 다음 에 dispatchTouch Event()방법 을 설정 해 야 합 니 다.안에서 도 제스처 사건 에 아래로 나 누 어 주어 야 합 니 다.제스처 판단 에 아래로 나 누 어 주지 않 으 면 Grid Layout 에서 클릭 이벤트 만 촉발 할 수 있 고 제스처 사건 은 작용 하지 않 습 니 다.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;
  }

그리고 새 successtoast_layot.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: 퍼 즐 게임
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기