当前位置: 代码迷 >> Android >> 活学活用——打造创意Android生日礼物(含拼图游戏,背景音乐,自动拨号等功能实现)
  详细解决方案

活学活用——打造创意Android生日礼物(含拼图游戏,背景音乐,自动拨号等功能实现)

热度:203   发布时间:2016-05-01 14:45:19.0
活学活用——制作创意Android生日礼物(含拼图游戏,背景音乐,自动拨号等功能实现)

        由于工作上的需要,得重头开始学习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





  相关解决方案