English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Believe it or not, many of us have played puzzle games when we were young. Now, with the widespread use of mobile phones, there are increasingly more games that can be played on them. So, to relive our childhood, I wrote this simple puzzle game, which can also further deepen our understanding of some basic knowledge of Android.
As usual, first is the effect diagram:
Here, I have randomized the image very little for demonstration purposes, which can be changed in the code.
Firstly, there is a default image that can be used for the puzzle, and you can also choose your favorite image for the puzzle. The process of the puzzle will record the number of moves, and a smiley prompt will pop up when the game is won, indicating the victory and the number of steps taken.
ps: Those interested can continue to expand on this, such as adding options for game difficulty, which can divide the image into more small blocks, etc.
Overall idea: divide the large image into individual small blocks, record the information of each small block with an array, display each small block with GridLayout, and mark a certain small block as a blank block (the blank block can be swapped with adjacent blocks), add click events to each small block on GridLayout and gesture events to the entire screen, judge whether the small block can be moved each time a click or gesture occurs, and finally pop up a victory prompt when the game is won.
Without further ado, let's proceed step by step to implement the puzzle game process.
1.Class related to small blocks.
This is the item of various variables of the small block, class, used to manage the information of each small block when the large image is divided into each small block. It's very simple, just various variables and Setter and Getter methods, here is the code~
/** * Created by yyh on 2016/10/21. */ public class GameItemView{ /** * Information of each small block */ //The actual x position of each small block, private int x=0; //The actual y position of each small block, private int y=0; //The image of each small block, private Bitmap bm; //The x position of the image of each small block, private int p_x=0; //The y position of the image of each small block. 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; } /** * Determine whether each small block is in the correct position * @return */ public boolean isTrue() { if (x == p_x && y == p_y) { return true; } return false; } }
2.Layout of the main interface
The main interface is simple, with a Button to change the image, an ImageView to display the original image, a GridLayout for the puzzle game, and finally, a TextView to display the number of steps taken to complete the puzzle. The layout is as follows:
<?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="Select image" 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> !-- The main interface of the game--> <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="Steps taken: 0" android:textSize="26sp" /> </RelativeLayout>
3Open image selection
Set the click event for Button to call the startActivityForResult(Intent intent, int requestCode) method to obtain an image.
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);//Open the album } });
Rewrite the onActivityResult(int requestCode, int resultCode, Intent data) method in Activity to display the selected picture and initialize the game. (After the picture selection is complete, the picture needs to be cut and the collage game needs to start.)
protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode){ case CHOICE_PHOTO: if (resultCode == RESULT_OK){ //Judging the phone system version if (Build.VERSION.SDK_INT >=19){ handleImageOnKitKat(data); //Get the picture in imageview BitmapDrawable bitmapDrawable = (BitmapDrawable) photo.getDrawable(); bt_tupan = bitmapDrawable.getBitmap(); //Remove the small squares from the original GridLayout, removeGameItem(); //Cut the new picture into small squares and add them to GridLayout. setGameItem(); //Start the game startGame(); } else { handleImageBeforeKitKat(data); //Get the picture in imageview BitmapDrawable bitmapDrawable = (BitmapDrawable) photo.getDrawable(); bt_tupan = bitmapDrawable.getBitmap(); //Remove the small squares from the original GridLayout, removeGameItem(); //Cut the new picture into small squares and add them to GridLayout. setGameItem(); //Start the game startGame(); } } } }
Then is the implementation function of the specific method to select the picture. The comments are very clear, no more words. Our focus is on the specific implementation of the collage and gesture changes, here there are many ways to select the picture. Not to elaborate, there are ready-made frameworks on the Internet.
//phone not greater than19the data retrieval method private void handleImageBeforeKitKat(Intent data) { Uri uri = data.getData(); String imagePath = getImagePath(uri, null); displayImage(imagePath); } /** * phone greater than19the data retrieval method * @param data */ @TargetApi(Build.VERSION_CODES.KITKAT) private void handleImageOnKitKat(Intent data) { String imagePath = null; Uri uri = data.getData(); if (DocumentsContract.isDocumentUri(this, uri)) { //If the url is of the document type, handle it through the document's id. String docId = DocumentsContract.getDocumentId(uri); if ("com.android.providers.media.documents".equals(uri.getAuthority())) { String id = docId.split(':')[1];//Parse out the id in numeric format; 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())) { //If the uri is not of the document type, handle it in the normal way. imagePath = getImagePath(uri, null); } displayImage(imagePath); } /** * Display the image * @param imagePath //The path of the image. */ private void displayImage(String imagePath) { if (imagePath != null) { Bitmap bitmap = BitmapFactory.decodeFile(imagePath); if (isHeigthBigWidth(bitmap)) { Bitmap bt = rotaingImageView(bitmap);//Rotate the image90 degrees. Bitmap disbitmapt = ajustBitmap(bt); photo.setImageBitmap(disbitmapt); } Bitmap disbitmap = ajustBitmap(bitmap); photo.setImageBitmap(disbitmap); } } } /** * Adjust the direction of the image * @param bitmap * @return */ private Bitmap rotaingImageView(Bitmap bitmap) { //Image rotation action Matrix matrix = new Matrix();; matrix.postRotate(270); // Create a new image Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); return resizedBitmap; } /** * Get the path of the image * @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.The formation process of each small block of the puzzle.
Looking at each small block, using GridLayout to implement is the most convenient. So, use a GridLayout to display the small blocks cut from the large image, use an ImageView array to save the information of each small block, and by default, set the last small block as an empty block.
First are all the necessary variables. The comments are very clear.
/** * Create several game small boxes using a two-dimensional array */ private ImageView[][] iv_game_arr = new ImageView[3][5]; /** *Game main interface * */ private GridLayout gl_game_layout; //Rows and columns of the small blocks private int i; private int j; /**Global variable for empty block*/ private ImageView iv_null_imagview;
Next, get the image from Imageview and cut the image according to certain rows and columns (here the puzzle is set to3Row5Columns). Store the information of each cut small block in an ImageView array. Set Tag and click listener for each small block.
private void setGameItem() { //Adjust the image size Bitmap abitmap = ajustBitmap(bt_tupan); int ivWidth = getWindowManager().getDefaultDisplay().getWidth()/5;//The width and height of each game block. Cut into squares 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++){ //Cut the large image into small blocks 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);//Set the pattern of each small block iv_game_arr[i][j].setLayoutParams(new RelativeLayout.LayoutParams(ivWidth, ivWidth)); //Set the spacing between the blocks iv_game_arr[i][j].setPadding(2, 2, 2, 2); iv_game_arr[i][j].setTag(new GameItemView(i, j, bm)); //Bind custom data iv_game_arr[i][j].setOnClickListener(new View.OnClickListener() { ....... );
Of course, the images we choose may not all be in standard sizes, so we need to adjust the image before cutting. Adjust the image to5:3ratio. (This will cut into3Row5The space between the small blocks needs to be calculated in advance for the correct cutting of the columns of small blocks) Here, I calculate the space between each small block for width.
//Adjust the size of the image 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; }
Place each small grid into the GridLayout.
/** * Place the small grid into GridLayout */ private void startGame() { tv_step.setText("Steps used: 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]); } } //Set the last block to the empty block. -1-1]
5. The click event and gesture judgment process of the small blocks.
This is the core of the puzzle game. Understanding the movement and change rules of the small blocks will also understand the puzzle game.
For the click event, first obtain various information (location, pattern) of the clicked small block and the location information of the empty small block, determine whether the clicked small block is adjacent to the empty small block. If adjacent, move and exchange data (using TranslateAnimation to implement the moving animation), if not adjacent, no operation is performed.
a. Method to determine whether the clicked block is adjacent to an empty block
/** * Determine whether the currently clicked block is adjacent to an empty block. * @param imageView The currently clicked block * @return true: Adjacent. false: Not adjacent. */ public boolean isAdjacentNullImageView(ImageView imageView){ //Get the position of the current empty block and the position of the clicked block 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()){//The block clicked is above the empty block return true; })else if(null_gameItemView.getY()==now_gameItem_view.getY()&&now_gameItem_view.getX()==null_gameItemView.getX()+1){//The block clicked is below the empty block return true; }else if(null_gameItemView.getY()==now_gameItem_view.getY()+1&&now_gameItem_view.getX()==null_gameItemView.getX(){//The block clicked is on the left side of the empty block return true; }else if(null_gameItemView.getY()+1==now_gameItem_view.getY()&&now_gameItem_view.getX()==null_gameItemView.getX(){ ////The block clicked is on the right side of the empty block return true; } return false; }
b. Next is the method for data exchange if adjacent
There is an overloaded method here, whether to have an animation effect. The data exchange without animation effect is prepared for shuffling the puzzle pieces when initializing the game. The core exchange code is listed here. After each exchange, it also needs to be judged whether the game is won (i.e., whether the puzzle is completed).
//Obtained the data bound to the clicked block GameItemView gameItemView = (GameItemView) itemimageView.getTag(); //Set the pattern of the empty block to the clicked block iv_null_imagview.setImageBitmap(gameItemView.getBm()); //Obtained the data bound to the empty block GameItemView null_gameItemView = (GameItemView) iv_null_imagview.getTag(); //Exchange data (pass the data of the clicked block to the empty block) null_gameItemView.setBm(gameItemView.getBm()); null_gameItemView.setP_x(gameItemView.getP_x()); null_gameItemView.setP_y(gameItemView.getP_y()); //Set the currently clicked block as the empty block. setNullImageView(itemimageView); if (isStart){ isGameWin();//A toast will pop up when successful. }
c. Animation settings during exchange
When swapping settings, first determine the direction of movement, set different moving animations according to the direction, and then listen for the animation to complete before performing data exchange operations. That is, after b. above, if adjacent, enter the block data exchange method. Finally, execute the animation.
//1.Create an animation, set the direction, and the distance to move //Determine the direction and set the animation if (itemimageView.getX() > iv_null_imagview.getX()){//The block clicked is above the empty block //move down translateAnimation = new TranslateAnimation(0.1f,-itemimageView.getWidth(), 0.1f, 0.1f); }else if (itemimageView.getX() < iv_null_imagview.getX()){//The block clicked is below the empty block //move up boolean f=itemimageView.getX() < iv_null_imagview.getX(); //Log.i("Click block","sssssssssssssssssssssssss"+f); translateAnimation = new TranslateAnimation(0.1f, itemimageView.getWidth(), 0.1f, 0.1f); }else if (itemimageView.getY() > iv_null_imagview.getY()){//The block clicked is on the left side of the empty block //move right translateAnimation = new TranslateAnimation(0.1f, 0.1f, 0.1f,-itemimageView.getWidth()); }else if(itemimageView.getY() < iv_null_imagview.getY()){//The block clicked is on the right side of the empty block //Move left translateAnimation = new TranslateAnimation(0.1f, 0.1f, 0.1f, itemimageView.getWidth()); } //2.Set various parameters of the animation translateAnimation.setDuration(80); translateAnimation.setFillAfter(true); //3.Set animation listener translateAnimation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { isAminMove = true; } @Override public void onAnimationEnd(Animation animation) { //Animation ends, exchange data ...... } //Animation execution itemimageView.startAnimation(translateAnimation);
The click event process is complete, and the next is the gesture judgment event. That is, not only can the small square be moved by clicking, but also by gesture to move the small square.
One. Create gesture object
Complete gesture-related operations in the onFling method.
//Create gesture object 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 e1MotionEvent e2, float distanceX, float distanceY) { return false; } @Override public void onLongPress(MotionEvent e) { } @Override public boolean onFling(MotionEvent e1MotionEvent e2public float velocityX, float velocityY) { //Gesture-related operations ...... }
Next, we perform specific operations in the onFling method
Two. Judge the direction of gesture movement
Determine different moving directions according to different return values.
/** * Increase gesture sliding, judge whether it is sliding up and down, left and right according to the gesture * @param start_x Gesture start point x * @param start_y Gesture start point y * @param end_x Gesture end point x * @param end_y Gesture end point y * @return 1: Up 2: Down 3: Left 4: Right */ public int getDirectionByGesture(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; //Whether it is left and right if(isLeftOrRight) {//Left and right boolean isLeft = (end_x-start_x)>0?false:true; if(isLeft) { return 3; } else { return 4; } } else {//Up and down boolean isUp = (end_y-start_y)>0?false:true; if (isUp) { return 1; } else { return 2; } } }
Three. Judge whether the empty block and the moving direction can move and perform the move operation.
Since it is a gesture, the blocks around the empty block must be moved, so the key is to judge the direction of the empty block to be moved, and then judge whether it can be moved according to the direction, and perform the move operation. (The changeDateByImageView() method is the specific operation of block exchange data and movement. It is the method of the click event.)
/**Override the changeByDirGes(int type) method; * Move adjacent blocks of the empty block according to the direction of the gesture. * @param type Return value of the direction 1: Up 2: Down 3: Left 5: Right * @param isAnim Whether there is animation true: There is animation, false: No animation */ public void changeByDirGes(int type, boolean isAnim) { //1Get the current position of the empty block. GameItemView null_gameItemView = (GameItemView) iv_null_imagview.getTag(); int new_x = null_gameItemView.getX(); int new_y = null_gameItemView.getY(); //2Set the corresponding adjacent position coordinates according to the direction. if (type==1){//It indicates that the empty block is above the block to be moved. new_x++; } else if (type==2){//The empty block is below the block to be moved new_x--; } else if (type==3){//The empty block is on the left side of the block to be moved new_y++; } else if (type==4){//The empty block is on the right side of the block to be moved new_y--; } //3Determine if the new coordinates exist if (new_x >= 0 && new_x < iv_game_arr.length && new_y >= 0 && new_y < iv_game_arr[0].length) { //Exists, can move and exchange data if (isAnim) {//With animation changeDateByImageView(iv_game_arr[new_x][new_y]); } else { changeDateByImageView(iv_game_arr[new_x][new_y], isAnim); } } else { //Do nothing } }
Well done, the gesture event is successfully implemented~
Of course, there are two things to pay attention to here.1Firstly, set the onTouchEvent() method for the current Activity to delegate touch events to the gesture handler. Secondly, also set the dispatchTouchEvent() method to forward the gesture events downwards. If not set to forward the gesture events, only click events can be triggered in the GridLayout, and gesture events will not take effect.2Firstly, add a flag to determine if the movement is in progress. If the movement is in progress, do nothing. Otherwise, every click on the small block will trigger a click event even during movement, causing unnecessary animation and a poor user experience.
@Override public boolean onTouchEvent(MotionEvent event) { return gestureDetector.onTouchEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { gestureDetector.onTouchEvent(ev); return super.dispatchTouchEvent(ev); }
6The method for shuffling blocks at the beginning of the game and displaying a Toast prompt at the end of the game.
The code is very simple, let's upload the code directly. Among them, the Toast popped out is a Toast with a custom View animation.
//Randomly shuffle the order of the pictures public void randomOrder(){ //The number of shuffles, set to be very small for convenience of testing. for (int i=0;i<5;i++){ //Exchange data according to the gesture, without animation. int type = (int) (Math.random()*4)+1; // Log.i("sssssssssfdfdfd", "Exchange times"+i+"The value of type"+type); changeByDirGes(type, false); } } /** * Method to determine if the game is over */ public void isGameWin(){ //Game victory flag boolean isGameWin = true; //Iterate through each small block for (i = 0; i < iv_game_arr.length; i++){ for (j = 0; j < iv_game_arr[0].length; j++){ //Do not judge the empty block and skip 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 out of the inner loop break; } } if (!isGameWin){ //Break out of the outer loop break; } } //Determine whether the game is over based on a switch variable, and give a prompt when it ends. if (isGameWin){ // Toast.makeText(this, "Game victory", Toast.LENGTH_SHORT).show(); ToastUtil.makeText(this, "Congratulations, you have won the game, it took"+step+"Step", ToastUtil.LENGTH_SHORT, ToastUtil.SUCCESS); step=0; } }
Alright, the important part is done. There is also a custom View Toast here. The detailed explanation of Toast will be in the next article. Here, we will briefly explain the implementation process of the custom Toast.
Firstly, create a SuccessToast class (including left eye, right eye, and smile curve). We will provide the core process. Use animation to achieve the dynamic process of drawing a smiling face.
@Override protected void onDraw(Canvas canvas) {}} super.onDraw(canvas); mPaint.setStyle(Paint.Style.STROKE); //Draw the smile arc canvas.drawArc(rectF, 180, endAngle, false, mPaint); mPaint.setStyle(Paint.Style.FILL); if (isSmileLeft) { //If it is the left eye, draw the left eye canvas.drawCircle(mPadding + mEyeWidth + mEyeWidth / 2, mWidth / 3, mEyeWidth, mPaint); } if (isSmileRight) { //If there is an eye, draw the right eye. canvas.drawCircle(mWidth - mPadding - mEyeWidth - mEyeWidth / 2, mWidth / 3, mEyeWidth, mPaint); } } /** * Method to start the animation * @param startF Start value * @param endF End value * @param time Animation time * @return */ private ValueAnimator startViewAnim(float startF, final float endF, long time) { //Set the starting and ending values of valueAnimator. valueAnimator = ValueAnimator.ofFloat(startF, endF); //Set the animation time valueAnimator.setDuration(time); //Set the interpolator. Control the rate of change of the animation valueAnimator.setInterpolator(new LinearInterpolator()); //Set the listener. Listen to the change of animation value and make corresponding actions. valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { mAnimatedValue = (float) valueAnimator.getAnimatedValue(); //If the value of value is less than 0.5 if (mAnimatedValue < 0.5) { isSmileLeft = false; isSmileRight = false; endAngle = -360 * (mAnimatedValue); //If the value of value is between 0.55and 0.7between }55 && mAnimatedValue < 0.7) { endAngle = -180; isSmileLeft = true; isSmileRight = false; //other } endAngle = -180; isSmileLeft = true; isSmileRight = true; } //redraw postInvalidate(); } }); if (!valueAnimator.isRunning()) { valueAnimator.start(); } return valueAnimator; }
Then create a success_toast_layout.xml to complete the toast layout. The layout is on the left and right (left smiley view, right TextView prompt).
<?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>
Finally, create a ToastUtil class to manage the custom 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(); } }
This way, you can call this custom Toast in ManiActivity.
Alright, done.
Game Source Code:Jigsaw Puzzle Gameimplementation process
gitHub:Jigsaw Puzzle Game.
That's all for this article. Hope it will be helpful to everyone's study, and also hope everyone will support the Yelling Tutorial more.
Declaration: The content of this article is from the Internet, the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, has not been edited by humans, and does not assume relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#w3Please report via email to codebox.com (replace # with @) when reporting, and provide relevant evidence. Once verified, this site will immediately delete the suspected infringing content.