1、MP3播放器java
查看Android API文檔能夠看到MediaPlayer狀態轉換圖:android
練習:shell
package com.shellway.mp3player; import java.io.File; import java.io.IOException; import android.support.v7.app.ActionBarActivity; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.content.Context; import android.media.MediaPlayer; import android.media.MediaPlayer.OnPreparedListener; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends ActionBarActivity { //媒體播放器 private MediaPlayer mp; private EditText songName; //以前是否暫停過 private boolean pause; private File file; private TelephonyManager tm; //暫停保存點 private int position = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); songName = (EditText) findViewById(R.id.song_name); tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); tm.listen(new MyPhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE); } private class MyPhoneStateListener extends PhoneStateListener{ @Override public void onCallStateChanged(int state, String incomingNumber) { // TODO Auto-generated method stub super.onCallStateChanged(state, incomingNumber); switch (state) { case TelephonyManager.CALL_STATE_IDLE://閒置狀態 if (position > 0 && mp != null) { //跳轉到指定的保存點位置 mp.seekTo(position); mp.start(); } break; case TelephonyManager.CALL_STATE_OFFHOOK://接聽狀態 if(mp != null){ if(mp.isPlaying()){ position = mp.getCurrentPosition(); mp.pause(); } } break; case TelephonyManager.CALL_STATE_RINGING://響鈴狀態 if (mp.isPlaying()) { position = mp.getCurrentPosition(); mp.pause(); } break; default: break; } } } //這裏是利用Activity生命週期的方法監聽來電時暫停播放 // @Override // protected void onResume() { // // TODO Auto-generated method stub // super.onResume(); // if(position > 0){ // //跳轉到指定的位置 // mp.seekTo(position); // mp.start(); // } // } // // @Override // protected void onPause() { // // TODO Auto-generated method stub // super.onPause(); // position = mp.getCurrentPosition(); // mp.pause(); // } public void play(View view){ String name = songName.getText().toString(); file = new File(Environment.getExternalStorageDirectory(),name+".mp3"); if (!file.exists()) { Toast.makeText(this, "文件不存在", Toast.LENGTH_SHORT).show(); mp=null; }else{ if (mp!=null) { if (mp.isPlaying()) { Toast.makeText(this, "歌曲已經在播放中", Toast.LENGTH_SHORT).show(); }else{ play(); } }else{ play(); } } } public void play(){ try { mp = new MediaPlayer(); //置爲初始狀態 mp.reset(); //指定要播放的文件 mp.setDataSource(file.getAbsolutePath()); //準備(緩衝) mp.prepare(); //設置緩衝完成監聽 mp.setOnPreparedListener(new MyOnPreparedListener()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private class MyOnPreparedListener implements OnPreparedListener{ @Override public void onPrepared(MediaPlayer mp) { // TODO Auto-generated method stub //播放 mp.start(); } } public void pause(View view){ if (mp.isPlaying()) { //暫停播放 mp.pause(); Button bt = (Button) view; bt.setText("繼續"); pause = true; }else{ if (pause) { mp.start(); Button bt = (Button) view; bt.setText("中止"); } } } public void stop(View view){ if (mp!=null) { //中止播放 mp.stop(); } } public void reset(View view){ if (mp!=null) { mp.start(); } } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); if (mp != null) { mp.release(); mp = null; } } }
<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="fill_parent" android:layout_height="wrap_content" android:text="請輸入歌曲名" /> <EditText android:id="@+id/song_name" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Complicated" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="play" android:text="播放" /> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="pause" android:text="暫停" /> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="stop" android:text="中止" /> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="reset" android:text="重播" /> </LinearLayout> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.shellway.mp3player" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <!-- 監聽來電狀態須要讀取電話狀態權限 --> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
運行結果截圖:app
二:MP4播放器ide
MP4的播放同MP3的差很少,主要是在顯示視頻的控件上的區別佈局
package com.shellway.mp4player; import java.io.File; import java.io.IOException; import android.support.v7.app.ActionBarActivity; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnPreparedListener; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends ActionBarActivity { private MediaPlayer mp; private EditText et_name; private File file; private boolean pause ; private SurfaceView surfaceview; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_name = (EditText) findViewById(R.id.et_name); surfaceview = (SurfaceView) findViewById(R.id.surfaceview); SurfaceHolder holder = surfaceview.getHolder(); //給SurfaceView設置屏幕分辨率 holder.setFixedSize(176, 144); //給SurfaceView設置保持高亮 holder.setKeepScreenOn(true); //不讓surfaceview維持本身的緩衝,讓它獲得的數據直接輸出 holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void play(View view){ String name = et_name.getText().toString(); file = new File(Environment.getExternalStorageDirectory(),name+".mp4"); Log.i("i", file.getAbsolutePath()); if (!file.exists()) { Toast.makeText(this, "播放文件不存在", Toast.LENGTH_SHORT).show(); }else{ //開始播放 play(); } } public void play(){ try { mp = new MediaPlayer(); mp.reset(); mp.setDataSource(file.getAbsolutePath()); //設置顯示畫面 mp.setDisplay(surfaceview.getHolder()); mp.prepare(); mp.setOnPreparedListener(new MyOnPreparedListener()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private class MyOnPreparedListener implements OnPreparedListener{ @Override public void onPrepared(MediaPlayer mp) { // TODO Auto-generated method stub mp.start(); } } public void pause(View view){ if (mp != null) { if (mp.isPlaying()) { mp.pause(); pause = true; }else{ mp.start(); pause = false; } } } public void stop(View view){ if (mp != null) { mp.stop(); } } public void reset(View view){ if (mp != null) { mp.reset(); play(); } } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); if (mp != null) { mp.release(); mp = null; } } }
<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="fill_parent" android:layout_height="wrap_content" android:text="請輸入要播放的視頻名稱:" /> <EditText android:id="@+id/et_name" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="test" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="10dp" android:onClick="play" android:src="@drawable/play" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="10dp" android:onClick="pause" android:src="@drawable/pause" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="10dp" android:onClick="stop" android:src="@drawable/stop" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="10dp" android:onClick="reset" android:src="@drawable/reset" /> </LinearLayout> <SurfaceView android:id="@+id/surfaceview" android:layout_width="fill_parent" android:layout_height="240dp" ></SurfaceView> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.shellway.mp4player" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
運行結果截圖:post
3、手機拍照測試
照相機的一些屬性:
預覽幀數:preview-frame-rate=30
圖片質量:jpeg-thumbnail-quality=90
圖片尺寸:preview-size-values=1280x720,800x480,768x432,720x480,640x480,480x320,176x144
SurfaceView只有當activity顯示到了前臺,該控件纔會被建立。
只有當surfaceView被建立了,才把相機所捕獲到的數據輸出給它。
若是activity回到回臺。surfaceview又會被銷燬
注意:在拍照的時候相機是被佔用的。拍照以後須要從新預覽。動畫
練習:ui
package com.shellway.takephoto; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import android.support.v7.app.ActionBarActivity; import android.hardware.Camera; import android.hardware.Camera.Parameters; import android.hardware.Camera.PictureCallback; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; import android.view.View; import android.view.Window; import android.view.WindowManager; public class MainActivity extends ActionBarActivity { private SurfaceView surfaceview; private Camera camera; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //請求窗體特徵:設置不顯示標題,注意要在setContentView以前設置 requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); //設置全屏幕顯示 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); surfaceview = (SurfaceView) findViewById(R.id.surfaceview); SurfaceHolder holder = surfaceview.getHolder(); //設置屏幕分辨率 holder.setFixedSize(176, 144); //設置屏幕保持高亮 holder.setKeepScreenOn(true); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); holder.addCallback(new MySurfaceCallback()); } private class MySurfaceCallback implements Callback{ @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub try { //打開相機 camera = Camera.open(); Parameters params = camera.getParameters(); //設置照片的尺寸 params.setPictureSize(800, 480); //設置預覽幀數,爲了兼容2.3之前版本仍是加上好 params.setPreviewFrameRate(5); //設置照片質量 params.setJpegQuality(80); camera.setParameters(params); //設置預覽顯示 camera.setPreviewDisplay(surfaceview.getHolder()); //設置開始預覽 camera.startPreview(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub } @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub //釋放相機資源 if (camera != null) { camera.release(); camera = null; } } } public void takephoto(View view){ //參數:shutter 開門被按下, raw 相機所捕獲的原始數據, jpeg 相機處理的數據 camera.takePicture(null, null, new MyPictureCallback()); } private class MyPictureCallback implements PictureCallback{ @Override public void onPictureTaken(byte[] data, Camera camera) { // TODO Auto-generated method stub try { File file = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".jpg"); FileOutputStream fos = new FileOutputStream(file); fos.write(data); //記得拍照存完數據到存儲卡後還要給相機設置繼續預覽 camera.startPreview(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void autofocus(View view){ //這裏是由相機硬件爲咱們自動對焦 } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); if (camera != null) { camera.release(); camera = null; } } }
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.shellway.takephoto.MainActivity" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> <SurfaceView android:id="@+id/surfaceview" android:layout_width="fill_parent" android:layout_height="fill_parent" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="10dp" android:onClick="autofocus" android:text="對焦" ></Button> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="10dp" android:text="拍照" android:onClick="takephoto" ></Button> </LinearLayout> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.shellway.takephoto" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <!-- 獲取相機的拍照權限 --> <uses-permission android:name="android.permission.CAMERA"/> <!-- 獲取外存儲設備的寫權限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <!-- 設置橫屏顯示屬性 screenOrientation--> <activity android:name=".MainActivity" android:label="@string/app_name" android:screenOrientation="landscape"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
運行結果截圖:下圖是在真實手機上運行的截圖
4、視頻刻錄
查看Android API文檔能夠看到MediaRecoder狀態轉換圖,用它來實現視頻的刻錄:
package com.shellway.videorecoder; import java.io.File; import java.io.IOException; import android.support.v7.app.ActionBarActivity; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Environment; import android.view.Menu; import android.view.MenuItem; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.Button; public class MainActivity extends ActionBarActivity { //聲明一個媒體刻錄機 private MediaRecorder mr; //由於是動態視圖,能夠用SurfaceView來展現 private SurfaceView surfaceview; private Button bt_start; private Button bt_stop; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); surfaceview = (SurfaceView) findViewById(R.id.surfaceview); SurfaceHolder holder = surfaceview.getHolder(); //設置屏幕分辨率 holder.setFixedSize(176, 144); //設置屏幕保持高亮 holder.setKeepScreenOn(true); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); bt_start = (Button) findViewById(R.id.bt_start); bt_stop = (Button) findViewById(R.id.bt_stop); } public void start(View view){ try { //建立一個媒體刻錄機 mr = new MediaRecorder(); //在給刻錄機設置屬性前首先要重置一下 mr.reset(); //設置音頻、視頻來源 mr.setAudioSource(MediaRecorder.AudioSource.MIC); mr.setVideoSource(MediaRecorder.VideoSource.CAMERA); //設置音頻、視頻輸出格式 mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); //設置音頻、視頻的編碼 mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); mr.setVideoEncoder(MediaRecorder.VideoEncoder.H264); //建立一個輸出音頻、視頻的文件 File file = new File(Environment.getExternalStorageDirectory(), System.currentTimeMillis()+".3gp"); mr.setOutputFile(file.getAbsolutePath()); //設置預覽 mr.setPreviewDisplay(surfaceview.getHolder().getSurface()); //準備刻錄 mr.prepare(); //開始刻錄 mr.start(); //開始刻錄後,按鈕可見的轉變 bt_start.setEnabled(false); bt_stop.setEnabled(true); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void stop(View view){ //中止刻錄 mr.stop(); //中止刻錄後,按鈕可見的轉變 bt_start.setEnabled(true); bt_stop.setEnabled(false); //釋放資源 mr.release(); mr = null; } }
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.shellway.videorecoder.MainActivity" > <SurfaceView android:id="@+id/surfaceview" android:layout_width="fill_parent" android:layout_height="fill_parent" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" > <Button android:id="@+id/bt_start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="10dp" android:onClick="start" android:text="開始" ></Button> <Button android:id="@+id/bt_stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="10dp" android:onClick="stop" android:enabled="false" android:text="中止" ></Button> </LinearLayout> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.shellway.videorecoder" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <!-- 使用相機的權限 --> <uses-permission android:name="android.permission.CAMERA"/> <!-- 媒體刻錄機的權限 --> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <!-- 外存儲寫的權限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <!-- 設置一開始就橫屏顯示 --> <activity android:name=".MainActivity" android:label="@string/app_name" android:screenOrientation="landscape"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
運行結果截圖:
五:手勢識別
首先,使用系統給出的應用Gestures Builder畫出手勢庫,而後把手勢庫導出到桌面,最後在工程res目錄下
新建一個raw文件(這個文件表示原文件,編譯的時候不會對它作任何修改),我這裏畫的一個打勾和「Z」字母,
打勾表示撥打電話號碼爲5556的電話,「Z」字母表示退出本應用程序。
練習:
package com.shellway.gestures; import java.util.ArrayList; import android.support.v7.app.ActionBarActivity; import android.R.anim; import android.content.Intent; import android.gesture.Gesture; import android.gesture.GestureLibraries; import android.gesture.GestureLibrary; import android.gesture.GestureOverlayView; import android.gesture.GestureOverlayView.OnGesturePerformedListener; import android.gesture.Prediction; import android.net.Uri; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; public class MainActivity extends ActionBarActivity { private GestureOverlayView gov; private GestureLibrary library; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); gov = (GestureOverlayView) findViewById(R.id.gov_id); //加載監聽 gov.addOnGesturePerformedListener(new MyOnGesturePerformedListener()); //加載手勢庫 library = GestureLibraries.fromRawResource(this, R.raw.gestures); library.load(); } private class MyOnGesturePerformedListener implements OnGesturePerformedListener{ @Override public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) { // 識別手勢 ArrayList<Prediction> predictions = library.recognize(gesture); if (predictions.isEmpty()) { Toast.makeText(getApplicationContext(),"手勢不存在", Toast.LENGTH_SHORT).show(); }else{ //拿到手勢庫裏面的第一個,即最匹配的手勢 Prediction prediction = predictions.get(0); //給匹配度打分,分是從0-10 double score = prediction.score; if (score>=6) { //手勢的名字 String name = prediction.name; if (name.equals("call")) { Intent intent = new Intent(); intent.setAction(Intent.ACTION_CALL); intent.setData(Uri.parse("tel:"+5556)); startActivity(intent); }else if(name.equals("exit")){ //利用殺死進程的方法退出程序 android.os.Process.killProcess(android.os.Process.myPid()); } }else{ Toast.makeText(getApplicationContext(),"匹配度過低", Toast.LENGTH_SHORT).show(); } } } } }
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <android.gesture.GestureOverlayView android:id="@+id/gov_id" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" ></android.gesture.GestureOverlayView> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="肯定" /> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="取消" /> </LinearLayout> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.shellway.gestures" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <!-- 撥打電話權限 --> <uses-permission android:name="android.permission.CALL_PHONE"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
運行結果截圖:
能夠支持多筆手勢:須要作以下改動
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <!-- 要支持多筆手勢就要加上gestureStrokeType這個屬性,由於默認是單筆手勢 --> <android.gesture.GestureOverlayView android:id="@+id/gov_id" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" android:gestureStrokeType="multiple" ></android.gesture.GestureOverlayView> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="ok" android:text="肯定" /> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="cancel" android:text="取消" /> </LinearLayout> </LinearLayout>
package com.shellway.gestures; import java.util.ArrayList; import android.support.v7.app.ActionBarActivity; import android.R.anim; import android.content.Intent; import android.gesture.Gesture; import android.gesture.GestureLibraries; import android.gesture.GestureLibrary; import android.gesture.GestureOverlayView; import android.gesture.GestureOverlayView.OnGestureListener; import android.gesture.GestureOverlayView.OnGesturePerformedListener; import android.gesture.Prediction; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.widget.Toast; public class MainActivity extends ActionBarActivity { private GestureOverlayView gov; private GestureLibrary library; private Gesture gesture; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); gov = (GestureOverlayView) findViewById(R.id.gov_id); //加載監聽 // gov.addOnGesturePerformedListener(new MyOnGesturePerformedListener()); //這個是支持多筆手勢的監聽 gov.addOnGestureListener(new MyOnGestureListener()); //加載手勢庫 library = GestureLibraries.fromRawResource(this, R.raw.gestures); library.load(); } private class MyOnGestureListener implements OnGestureListener{ @Override public void onGestureStarted(GestureOverlayView overlay, MotionEvent event) { // TODO Auto-generated method stub Log.i("i", " onGestureStarted "); } @Override public void onGesture(GestureOverlayView overlay, MotionEvent event) { // TODO Auto-generated method stub Log.i("i", " onGesture "); } @Override public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) { // TODO Auto-generated method stub Log.i("i", " onGestureEnded "); //拿到當前的手勢 gesture = overlay.getGesture(); } @Override public void onGestureCancelled(GestureOverlayView overlay, MotionEvent event) { // TODO Auto-generated method stub Log.i("i", " onGestureCancelled "); } } private class MyOnGesturePerformedListener implements OnGesturePerformedListener{ @Override public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) { //overlay:表示當前的手勢,gesture表示最後的手勢 recognize(gesture); } } public void ok(View view){ recognize(gesture); gov.clear(true); } public void cancel(View view){ gov.clear(true); } // 識別手勢 private void recognize(Gesture gesture) { ArrayList<Prediction> predictions = library.recognize(gesture); if (predictions.isEmpty()) { Toast.makeText(getApplicationContext(),"手勢不存在", Toast.LENGTH_SHORT).show(); }else{ //拿到手勢庫裏面的第一個,即最匹配的手勢 Prediction prediction = predictions.get(0); //給匹配度打分,分是從0-10 double score = prediction.score; if (score>=6) { //手勢的名字 String name = prediction.name; if (name.equals("call")) { Intent intent = new Intent(); intent.setAction(Intent.ACTION_CALL); intent.setData(Uri.parse("tel:"+5556)); startActivity(intent); }else if(name.equals("exit")){ //利用殺死進程的方法退出程序 android.os.Process.killProcess(android.os.Process.myPid()); } }else{ Toast.makeText(getApplicationContext(),"匹配度過低", Toast.LENGTH_SHORT).show(); } } } }
多筆手勢監聽方法的測試:
8、通知:Notification
以前咱們學了提示用戶的兩種方式:Toast 、AlertDialog
如今咱們來看看通知Noitification,它主要由如下六部分組成:
圖標、ticker提示信息、時間、標題、內容、事件
練習:
package com.shellway.notification; import android.support.v7.app.ActionBarActivity; import android.R.anim; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.RemoteViews; public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void notification(View view){ //獲得通知管理器 NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); //構建通知 Notification notification = new Notification(android.R.drawable.stat_notify_chat, "這是一個提示信息", System.currentTimeMillis()); //通知的點擊事件 Intent intent = new Intent(this,MainActivity.class); //第二個參數爲請求碼,可隨意指定。第四個參數爲標誌碼,咱們這裏填0就能夠了 PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, intent, 0); notification.setLatestEventInfo(this, "通知標題", "通知內容", pendingIntent); //點擊後消失 notification.flags = Notification.FLAG_AUTO_CANCEL; //發送通知 notificationManager.notify(100, notification); } public void customnotification(View view){ //獲得通知管理器 NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); //構建通知 Notification notification = new Notification(); notification.icon = android.R.drawable.stat_notify_call_mute;//圖標 notification.tickerText = "新的信息來啦";//通知提示信息 //自定義通知內容佈局 RemoteViews remoteviews = new RemoteViews(getPackageName(), R.layout.contentview); notification.contentView = remoteviews; //定義通知內容 Intent intent = new Intent(this,MainActivity.class); PendingIntent paIntent = PendingIntent.getActivity(this, 100, intent, 0); notification.contentIntent = paIntent; //點擊後消失 notification.flags = Notification.FLAG_AUTO_CANCEL; //發送通知 notificationManager.notify(100, notification); } }
package com.shellway.notification; import android.app.Activity; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; public class OtherActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.contentview); } }
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="notification" android:text="普統統知" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="customnotification" android:text="自定義通知" /> </LinearLayout>
<?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="horizontal" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="新收到10條短信" /> <ProgressBar android:layout_width="fill_parent" android:layout_height="wrap_content" style="@android:style/Widget.ProgressBar.Horizontal" ></ProgressBar> </LinearLayout> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.shellway.notification" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".OtherActivity"></activity> </application> </manifest>
運行結果截圖:
9、動畫(Animation)
咱們能夠查官方文檔中API Guies能夠看到
根據它,咱們能夠進行以上提到的兩種動畫的開發工做
練習1:tween動畫,首先在res目錄下新建文件夾anim,而後在其下面創建動畫xml文件
package com.example.tweenanimation; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.ImageView; public class MainActivity extends ActionBarActivity { private ImageView iv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iv = (ImageView) findViewById(R.id.iv); } public void start(View view){ //加載動畫 // Animation anim = AnimationUtils.loadAnimation(this, R.anim.alpha);//圖片透明度 // Animation anim = AnimationUtils.loadAnimation(this, R.anim.scale);//圖片縮放 // Animation anim = AnimationUtils.loadAnimation(this, R.anim.translate);//圖片移動 // Animation anim = AnimationUtils.loadAnimation(this, R.anim.rotate);//圖片旋轉 Animation anim = AnimationUtils.loadAnimation(this, R.anim.set);//以上綜合 //執行動畫 iv.startAnimation(anim); } }
<?xml version="1.0" encoding="utf-8"?> <!-- FillAfter,動畫的最後一幀是否保持在View上面,FillEnabled是否啓用Fill保持 --> <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:fromAlpha="1" android:toAlpha="0" android:duration="2000" android:fillAfter="true" > </alpha>
<?xml version="1.0" encoding="utf-8"?> <!-- pivotX 若填5表示旋轉5個像素, 若填5%表示相對自身旋轉5%,若填5%p表示相對父元素旋轉--> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="0" android:toDegrees="90" android:pivotX="50%" android:pivotY="50%" android:duration="2000" > </rotate>
<?xml version="1.0" encoding="utf-8"?> <!-- FillAfter,動畫的最後一幀是否保持在View上面,FillEnabled是否啓用Fill保持 --> <scale xmlns:android="http://schemas.android.com/apk/res/android" android:fromXScale="1" android:toXScale="2" android:fromYScale="1" android:toYScale="0.5" android:duration="2000" android:fillAfter="true" > </scale>
<?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromXDelta="0" android:toXDelta="100" android:fromYDelta="0" android:toYDelta="100" android:fillAfter="true" android:duration="2000" > </translate>
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <alpha android:fromAlpha="1" android:toAlpha="0" android:duration="2000" android:fillAfter="true" /> <scale android:fromXScale="1" android:toXScale="2" android:fromYScale="1" android:toYScale="0.5" android:duration="2000" android:fillAfter="true" /> <translate android:fromXDelta="0" android:toXDelta="100" android:fromYDelta="0" android:toYDelta="100" android:fillAfter="true" android:duration="2000" /> <rotate android:fromDegrees="0" android:toDegrees="90" android:pivotX="50%" android:pivotY="50%" android:duration="2000" /> </set>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ImageView android:id="@+id/iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="start" android:text="開始" /> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.tweenanimation" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
練習2:frame動畫,首先在res目錄下新建drawable文件夾,而後在其下加入要用到的圖片資源和資源xml文件
package comshellway.frameanimation; import android.support.v7.app.ActionBarActivity; import android.graphics.drawable.AnimationDrawable; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.ImageView; public class MainActivity extends ActionBarActivity { private AnimationDrawable ad; private ImageView iv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iv = (ImageView) findViewById(R.id.iv); } //開始動畫 public void start(View view){ //通常frame動畫用來做背景用,在這裏是獲得背景動畫 ad = (AnimationDrawable) iv.getBackground(); ad.start(); } //中止動畫 public void stop(View view){ ad.stop(); } }
<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="true" > <item android:drawable="@drawable/a1" android:duration="200" /> <item android:drawable="@drawable/a2" android:duration="200" /> <item android:drawable="@drawable/a3" android:duration="200" /> <item android:drawable="@drawable/a4" android:duration="200" /> <item android:drawable="@drawable/a5" android:duration="200" /> <item android:drawable="@drawable/a6" android:duration="200" /> <item android:drawable="@drawable/a7" android:duration="200" /> <item android:drawable="@drawable/a8" android:duration="200" /> <item android:drawable="@drawable/a9" android:duration="200" /> <item android:drawable="@drawable/a10" android:duration="200" /> <item android:drawable="@drawable/a11" android:duration="200" /> <item android:drawable="@drawable/a12" android:duration="200" /> <item android:drawable="@drawable/a13" android:duration="200" /> <item android:drawable="@drawable/a14" android:duration="200" /> <item android:drawable="@drawable/a15" android:duration="200" /> </animation-list>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ImageView android:id="@+id/iv" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/frame" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="start" android:text="開始" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="stop" android:text="中止" /> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="comshellway.frameanimation" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
運行結果截圖:
10、傳感器
練習:
package com.shellway.sensor; import android.support.v7.app.ActionBarActivity; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.animation.Animation; import android.view.animation.RotateAnimation; import android.widget.ImageView; public class MainActivity extends ActionBarActivity { private MySensorEventListener listener; private SensorManager sensorManager; private Sensor sensor; private ImageView iv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iv = (ImageView) findViewById(R.id.iv); //得到傳感器管理器 sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); //得到方向傳感器 sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); listener = new MySensorEventListener(); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); //註冊sensor監聽 sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_GAME); } private class MySensorEventListener implements SensorEventListener{ private float predegree = 0; @Override public void onSensorChanged(SensorEvent event) { // TODO Auto-generated method stub float x = event.values[SensorManager.DATA_X]; //建立一個旋轉的動畫,0.5f表示自身的正中間,Animation.RELATIVE_TO_SELF表示相對自身旋轉 RotateAnimation rotate = new RotateAnimation(-predegree, x, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotate.setDuration(50); iv.startAnimation(rotate); predegree = x; } //精確度的改變,這裏暫時不用管 public void onAccuracyChanged(Sensor sensor, int accuracy) { // TODO Auto-generated method stub } } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); //當應用在前臺不活動的時候取消監聽 sensorManager.unregisterListener(listener); } }
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.shellway.sensor.MainActivity" > <ImageView android:id="@+id/iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:src="@drawable/zn" /> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.shellway.sensor" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
運行結果截圖:
十一:圖片的移動和縮放
分析:
練習:
package com.shellway.dragscale; import android.support.v7.app.ActionBarActivity; import android.graphics.Matrix; import android.graphics.PointF; import android.os.Bundle; import android.util.FloatMath; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.ImageView; public class MainActivity extends ActionBarActivity { private ImageView iv; private MyOnTouchListener listener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listener = new MyOnTouchListener(); iv = (ImageView) findViewById(R.id.iv); iv.setOnTouchListener(listener); } private class MyOnTouchListener implements OnTouchListener{ private PointF startPiont = new PointF();//起始點 private Matrix mcurrentMatrix = new Matrix();//圖片當前的matrix值 private Matrix mMatrix = new Matrix();//來一個臨時的matrix private int type = 0; private final static int DRAG = 1; private final static int SCALE = 2; private PointF mstartP;//中心點 private float mdistance;//兩點間的距離 @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction()&MotionEvent.ACTION_MASK; switch (action) { case MotionEvent.ACTION_DOWN://當手指按下 float x = event.getX(); float y = event.getY(); startPiont.set(x, y);// mcurrentMatrix.set(iv.getImageMatrix());//圖片尚未被拖動時候的位置 type = DRAG; break; case MotionEvent.ACTION_POINTER_1_DOWN://屏幕上已經有一根手指,再按下一根手指 mcurrentMatrix.set(iv.getImageMatrix());//圖片尚未被縮放時候的大小 mstartP = getMidPoint(event);//獲得移動前兩個手指間的中心位置 mdistance = getMidDistance(event);//獲得移動前兩個手指間的距離 type = SCALE; break; case MotionEvent.ACTION_MOVE://當手指移動 if (type == DRAG) { mMatrix.set(mcurrentMatrix); float dx = event.getX() - startPiont.x; float dy = event.getY() - startPiont.y; mMatrix.postTranslate(dx, dy); }else if(type == SCALE){ mMatrix.set(mcurrentMatrix); float distance = getMidDistance(event);//獲得移動後兩個手指間的距離 float sx = distance/mdistance; mMatrix.postScale(sx, sx, mstartP.x, mstartP.y); } break; case MotionEvent.ACTION_UP://當手指彈起 case MotionEvent.ACTION_POINTER_1_UP://屏幕上彈起一根手指,還有一根手指 type = 0; break; default: break; } //給界面設置變更後的數據 iv.setImageMatrix(mMatrix); return true; } //計算中心點位置 public PointF getMidPoint(MotionEvent event){ float x = (event.getX(1) + event.getX(0))/2; float y = (event.getY(1) + event.getY(0))/2; return new PointF(x,y); } //計算兩點間的距離 public float getMidDistance(MotionEvent event){ float dx = event.getX(1) - event.getX(0); float dy = event.getY(1) - event.getY(0); return FloatMath.sqrt((dx*dx) + (dy*dy)); } } }
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.shellway.dragscale.MainActivity" > <!--scaleType表示縮放類型, matrix表示圖片的位置和大小 --> <ImageView android:id="@+id/iv" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="matrix" android:src="@drawable/family" /> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.shellway.dragscale" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
運行結果截圖: