編輯:關於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:拼圖游戲。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。
smalidea smalidea是一個IntelliJ IDEA/Android Studio smali語言插件,可實現動態調試smali代碼。 github地址
前言:上篇介紹了自定義控件的基本要求以及繪制的基本原理,本篇文章主要介紹如何給自定義控件自定義一些屬性。本篇文章將繼續以上篇文章自定義圓形百分比為例進行講解。有關原理知識
本Demo中所含功能1:定位,顯示當前位置2:地圖多覆蓋物(地圖描點,彈出該點的詳細信息)3:坐標地址互相換算4:POI興趣點檢索5:線路查詢(步行,駕車,公交)6:繪制
配置前gradle文件內容: 配置完成gradle文件內容: 接下來正式開始啦~一、打開配置頁面,按照一下順序操作,myconfig只是我隨意取得一個名字,可以根據自己喜