由于工作上的需要,得重头开始学习Android开发,刚开始学了几个星期吧,想这么光看书没实践的话效率会很低,刚好朋友的生日快到了,于是就萌生出弄个APP送给人家的想法。于是乎动力十足,加班加点,赶在生日时候送出去了。最后我秉着安卓开源的精神,特将我的源代码共享出来,并且进行必要注释,希望能够共同学习和提高,由于个人隐私问题,采取的图片已经修改,自动拨号改为拨给10086.
进入正题,先看下几张效果图:
整个项目的主要思想和步骤是:
1.个性化安装图标的定制。
2.进入程序,播放背景音乐。
3.进行拼图游戏。
4.游戏过关后进入下一个界面,有两个按钮,点击即可实现给指定号码拨号功能。
由于源码我注释得也比较清楚了,直接上源码给大家看吧~
第一个界面的实现代码,Main.java
// file: Main.java// 2012-09-12 By 周军Dream_Flypackage com.example.zhangbeta2;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;public class Method extends Activity{ Button backBtn = null; @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.method); backBtn = (Button)findViewById(R.id.backBtn); backBtn.setOnClickListener(new backOnClickListener()); } class backOnClickListener implements OnClickListener{ @Override public void onClick(View v) { // TODO Auto-generated method stub finish(); } }}跳转到第二个界面的实现代码,SePintu.java
// file: SePintu.java// 2012-09-12 By 周军Dream_Flypackage com.example.zhangbeta2;import android.app.Activity;import android.app.AlertDialog;import android.app.AlertDialog.Builder;import android.content.DialogInterface;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Matrix;import android.graphics.drawable.BitmapDrawable;import android.os.Bundle;import android.view.Gravity;import android.view.View;import android.view.View.OnClickListener;import android.view.WindowManager;import android.widget.ImageView;import android.widget.ImageView.ScaleType;import android.widget.Button;import android.widget.LinearLayout;public class SePintu extends Activity{ private int levelNow = 4; private ImageView mImages[][]; //存放小图片的数组 private Bitmap mBitmap; //资源图片 private int mImageWidth = 0, mImageHeight = 0; //slot的宽高 private int mImageNum[]; //图片的顺序 private int x = 0, y = 0; //图片的起始位置 private int clickNum = 0; //点击参数 private int windowWidth = 0, windowHeight = 0; //屏幕参数 public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState);// pic1 = (ImageView)findViewById(R.id.pic1); mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pic1); System.out.println("width = " + mBitmap.getWidth() + "height = " + mBitmap.getHeight()); //屏幕参数 WindowManager w = this.getWindowManager(); windowHeight = w.getDefaultDisplay().getHeight(); windowWidth = w.getDefaultDisplay().getWidth(); System.out.println("wWidth = " + windowWidth + "wHeight = " + windowHeight); setImage(); } public void setImage() { mImageWidth = mBitmap.getWidth() / levelNow; //切割图片,每一小块的宽度 mImageHeight = mBitmap.getHeight() / levelNow; mImageNum = new int[levelNow * levelNow]; System.out.println("mIWidth = " + mImageWidth + "mImageHeight = " + mImageHeight); erraLen(levelNow * levelNow); //随机组合切碎的小图片 readyImage(); setLayout(); //布局随机组合后的图片 } private void setLayout() { PictureLayout lay = new PictureLayout(this, mImages); //利用带参数的构造函数来布局小图片 lay.setOrientation(LinearLayout.VERTICAL); lay.setGravity(Gravity.CENTER_HORIZONTAL); setContentView(lay); //显示lay布局,SePintu的Activity Button methodButton = new Button(this); methodButton.setText(R.string.method_btn_label); methodButton.setOnClickListener(new MethodBtnClick()); //添加监听器 Button showSourceImageBtn = new Button(this); showSourceImageBtn.setText(R.string.show_source_image_btn_label); showSourceImageBtn.setOnClickListener(new SourceBtnClick()); LinearLayout linear = new LinearLayout(this); //注意,对于LinearLayout布局来说,设置横向还是纵向是必须的!否则就看不到效果了。 linear.setOrientation(LinearLayout.HORIZONTAL); //此处相当于布局文件中的Android:gravity属性 linear.setGravity(Gravity.CENTER_HORIZONTAL); methodButton.setWidth(200); showSourceImageBtn.setWidth(200); linear.addView(methodButton); //通过addView将两按钮添加到布局中 linear.addView(showSourceImageBtn); lay.addView(linear); //把linear当作子child添加到lay布局中 } class MethodBtnClick implements OnClickListener{ @Override public void onClick(View v) { // TODO Auto-generated method stub Intent intent = new Intent(); intent.setClass(SePintu.this, Method.class); startActivity(intent); //跳转Activity } } class SourceBtnClick implements OnClickListener{ @Override public void onClick(View v) { // TODO Auto-generated method stub Intent intent = new Intent(SePintu.this, SourceImageAty.class); startActivity(intent); //跳转Activity } } /** * @see 把一个有序数组通过随机取数打乱 * @param a */ public void erraLen(int a) { int errInt[] = new int[a]; for (int i = 0; i < a; i++) { errInt[i] = i; } int len = a;// 设置随机数的范围 for (int i = 0; i < a; i++) { int index = (int) Math.floor((Math.random() * len)); mImageNum[i] = errInt[index]; for (int j = index; j < errInt.length - 1; j++) { // 把选中的数之后的数一次向前移一位,因为index选中的数已经存放在相应的mImageNum里面了, errInt[j] = errInt[j + 1]; } len--;// 随机数的范围减一 } } /** * @see 准备图片 把一张图片截成几张小的通过打乱的数组来取cache里的图片放到View里面就成打乱二维数组 */ private void readyImage() { Matrix matrix = new Matrix(); mImages = new ImageView[levelNow][levelNow]; // 设置缩放比例// float scaleW = ((float) mBitmap.getWidth()) / mBitmap.getWidth();// float scaleH = ((float) mBitmap.getHeight()) / mBitmap.getHeight(); float scaleW = ((float) mBitmap.getWidth()) / (windowWidth + 180); float scaleH = ((float) mBitmap.getHeight()) / (windowHeight + 180); System.out.println("scaleW = " + scaleW +" scaleH" + scaleH); float scale = scaleW > scaleH ? 1 / scaleW : 1 / scaleH; //scale是缩放比例,取最小比例的进行缩放 System.out.println("scale = " + scale); matrix.postScale(scale, scale); Bitmap bitss[][] = new Bitmap[levelNow][levelNow]; ImageView[][] cache = new ImageView[levelNow][levelNow]; int cont = 1; for (int i = 0; i < levelNow; i++) { for (int j = 0; j < levelNow; j++) { int x = i * mImageWidth; int y = j * mImageHeight; // 第一个是要在那个图片上截取 x,y是要在这个图的那个位置截取 // mImageWidth,mImageHeight是截取的长和宽, matrix是缩放比例 Bitmap mapi = Bitmap.createBitmap(mBitmap, x, y, mImageWidth, mImageHeight, matrix, true); bitss[i][j] = mapi; ImageView img = new ImageView(this); BitmapDrawable draw = new BitmapDrawable(bitss[i][j]); img.setImageDrawable(draw); img.setId(cont); img.setScaleType(ScaleType.FIT_XY); img.setOnClickListener(OnClickImageView1); cache[i][j] = img; //cache存放着整张图切割后的小图片 cont++; } } for (int i = 0; i < mImageNum.length; i++) { int x = mImageNum[i] / levelNow; //确定第几行 int y = mImageNum[i] % levelNow; //确定第几列 int x1 = i / levelNow; int y1 = i % levelNow; mImages[x1][y1] = cache[x][y]; //将cache里面的小图片随机放入mImages数组里面 } } private android.view.View.OnClickListener OnClickImageView1 = new ImageView.OnClickListener() { @Override public void onClick(View v) { if (clickNum == 0) {// 即需要交换的第一个图片 for (int i = 0; i < mImages.length; i++) { boolean f = false; for (int j = 0; j < mImages[i].length; j++) { ImageView imgg = mImages[i][j]; if (imgg == v) { //所点击的刚好是指定的小图片区域 x = i; y = j; clickNum++; //点击了一次 f = true; break; } } if (f) { break; } } } else {// 即需要交换的第二个图片 for (int i = 0; i < mImages.length; i++) { for (int j = 0; j < mImages[i].length; j++) { ImageView imgg = mImages[i][j]; if (imgg == v) { if (clickNum == 1) { changePosition(i, j, x, y); x = 0; y = 0; clickNum = 0; } } } } } } }; private void changePosition(int x1, int y1, int x2, int y2) { // 判断宽和高差的绝对值是否是1,如果是1的话交换两张图片,不是1的话提示用户 if (Math.abs(x1 - x2) + Math.abs(y1 - y2) != 1) { System.out.println("not link...."); Builder bul = new AlertDialog.Builder(this); //弹出相应对话框 bul.setTitle(R.string.dialog); bul.setMessage(R.string.cannot_change); bul.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }).show(); } else { //相邻,两张图片进行交换 System.out.println("link...."); String str = ""; ImageView bitF = null; bitF = mImages[x1][y1]; mImages[x1][y1] = mImages[x2][y2]; mImages[x2][y2] = bitF; for (int i = 0; i < mImages.length; i++) { for (int j = 0; j < mImages[i].length; j++) { ImageView img = mImages[i][j]; //得到ImageView的父控件 LinearLayout pa = (LinearLayout) img.getParent(); // 再移除ImageView使其父控件没有,移除父控件,重新用setLayout()进行布局 pa.removeView(img); } } setLayout(); //将进行变换操作的图片显示出来 for (int i = 0; i < mImages.length; i++) { for (int j = 0; j < mImages[i].length; j++) { str += mImages[i][j].getId(); //取对应小图片的ID,相当于R.id.mImages[i][j] } } //根据具体切割次数levelNow,判断最后一次变换是否已经拼好 switch (levelNow) { case 2: if (str.equals("1324")) { // “1324”的意思是,将图片2*2地切割,有四块,标号先竖着,然后再横着来1234,根据getId取值互相比较 this.success(); } break; case 3: if (str.equals("147258369")) { this.success(); } break; case 4: if (str.equals("15913261014371115481216")) { this.success(); } break; case 5: if (str.equals("16111621271217223813182349141924510152025")) { this.success(); } break; } } } public void success() { Builder bul = new AlertDialog.Builder(this); bul.setTitle(R.string.dialog); bul.setMessage(R.string.congratulation); bul.setPositiveButton(R.string.next_Label, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent(SePintu.this, TheEnd.class); SePintu.this.startActivity(intent); //点击确定后跳转到下一个Activity } }); bul.show(); System.out.println("success"); }}通过构造函数,进行画图布局,PictureLayout.java
// file: PictureLayout.java// 2012-09-12 By 周军Dream_Flypackage com.example.zhangbeta2;import android.content.Context;import android.widget.ImageView;import android.widget.LinearLayout;public class PictureLayout extends LinearLayout{ public PictureLayout(Context context, ImageView[][] images) { super(context); setLayout(context, images); setBackgroundColor(0xffff7777); //为了和照片边缘区分开,我添加了背景颜色 } private void setLayout(Context context, ImageView[][] view) { LinearLayout linralayout = new LinearLayout(context); linralayout.setOrientation(LinearLayout.VERTICAL); linralayout.setPadding(0, 0, 0, 0); for (int i = 0; i < view.length; i++) { LinearLayout liner = new LinearLayout(context); liner.setOrientation(LinearLayout.HORIZONTAL); int leng = view[i].length; for (int j = 0; j < leng; j++) { ImageView img = (ImageView) view[i][j]; liner.addView(img); } linralayout.addView(liner); liner = null; } this.addView(linralayout); }}
//游戏原图显示
// file: SourceImageAty.java
// 2012-09-12 By 周军Dream_Flypackage com.example.zhangbeta2;import android.app.Activity;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.ImageView;public class SourceImageAty extends Activity{ private ImageView pic1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.source); pic1 = (ImageView)findViewById(R.id.pic1); Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.pic1); pic1.setImageBitmap(bitmap1); pic1.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { // TODO Auto-generated method stub finish(); //点击屏幕图片即退出当前Activity } }); }}游戏方法Activity, Method.java
// file: Method.java// 2012-09-12 By 周军Dream_Flypackage com.example.zhangbeta2;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;public class Method extends Activity{ Button backBtn = null; @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.method); backBtn = (Button)findViewById(R.id.backBtn); backBtn.setOnClickListener(new backOnClickListener()); } class backOnClickListener implements OnClickListener{ @Override public void onClick(View v) { // TODO Auto-generated method stub finish(); } }}最后界面,
// file: TheEnd.java// 2012-09-12 By 周军Dream_Flypackage com.example.zhangbeta2;import android.app.Activity;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;public class TheEnd extends Activity{ private Intent intentMusic = new Intent("com.angel.Android.MUSIC"); @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.end); setCompenent(); } private void setCompenent(){ Button callExitBtn = (Button)findViewById(R.id.call_exit); callExitBtn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { // TODO Auto-generated method stub Intent intent = new Intent( Intent.ACTION_CALL, Uri.parse("tel:10086")); //自动拨号,由于隐私,改成10086.。。 stopService(intentMusic); startActivity(intent); } }); Button exitCallBtn = (Button)findViewById(R.id.exit_call); exitCallBtn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { // TODO Auto-generated method stub Intent intent = new Intent( Intent.ACTION_CALL, Uri.parse("tel:10086")); stopService(intentMusic); startActivity(intent); } }); }}
背景音乐实现,MusicServer.java
// file: MusicServer.java// 2012-09-12 By 周军Dream_Flypackage com.example.zhangbeta2;import android.app.Service; import android.content.Intent;import android.media.MediaPlayer;import android.os.IBinder; public class MusicServer extends Service { private MediaPlayer mediaPlayer; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } @Override public void onStart(Intent intent,int startId){ super.onStart(intent, startId); if(mediaPlayer==null){ // R.raw.happy是资源文件,MP3格式的,存放在res资源下raw文件夹里,没有的话新建个 mediaPlayer = MediaPlayer.create(this, R.raw.happy); mediaPlayer.setLooping(true); mediaPlayer.start(); } } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); mediaPlayer.stop(); }}
JAVA文件就这些,剩下就是xml文件了。
main.xml文件如下
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:background="@drawable/background"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#abcdef" android:text="@string/hello_world" tools:context=".Main" /> <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:id="@+id/buttonNext" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="@string/next" /> <Button android:id="@+id/buttonExit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="@string/exit" /> </LinearLayout></LinearLayout>
method.xml文件如下
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/method_detail"/> <Button android:id="@+id/backBtn" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/back_label"/></LinearLayout>
source.xml文件如下
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:background="#ffff7777"> <ImageView android:id="@+id/pic1" android:layout_width="fill_parent" android:layout_height="fill_parent"> </ImageView></LinearLayout>
end.xml文件如下
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:background="@drawable/cake_bak"> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/call_exit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="@string/call_exit"/> <Button android:id="@+id/exit_call" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="@string/exit_call"/> </LinearLayout></LinearLayout>
AndroidManifest.xml文件如下
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.zhangbeta2" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".Main" android:label="@string/title_activity_main" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".SePintu" android:label="@string/label_pintu1"/> <activity android:name=".Method" android:label="@string/method_label"/> <activity android:name=".TheEnd" android:label="@string/label_theEnd"/> <activity android:name=".SourceImageAty" android:label="@string/source_back_label"/> <service android:name=".MusicServer"> <intent-filter> <action android:name="com.angel.Android.MUSIC"/> <category android:name="android.intent.category.default" /> </intent-filter> </service> </application> <uses-permission android:name="android.permission.CALL_PHONE"></uses-permission> </manifest>
在我的测试中,我发现存在以下几个问题,(1)当我用Service来播放背景音乐时候,如果是通过键盘上返回键退出的话,就不会stopService,背景音乐就一直播放,由于赶着送出去的时间关系,我没有修复它,上网查了下可以通过重写onKeyDown按键,来实现关闭音乐。(2)分辨率的问题,我主要是针对4.0屏幕设计的,有时候用的是fill_parent,有时候不同屏幕会造成图片的变形。若各位有更好的方法,欢迎交流。
应用程序APK下载地址:http://download.csdn.net/detail/jjzhoujun2010/4568777
源码下载地址:http://download.csdn.net/detail/jjzhoujun2010/4568770
参考文章: - - 不好意思,综合看得太多了,记不得那个了,其中拼图的打乱算法我是参考别人的,若有人看到此文章,请告诉我链接,多谢。
原创文章,欢迎转载,转载请注明:blog.csdn.net/jjzhoujun2010
作者:Dream Fly 新浪微博:周军Dream_Fly