java攻城獅之路(Android篇)--MP3 MP四、拍照、國際化、樣式主題、圖片移動和縮放

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;
        }
    }
}
MainActivity.java
<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>
activity_main.xml
<?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>
AndroidManifest.xml

運行結果截圖: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;
        }
    }
}
MainActivity.java
<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>
activity_main.xml
<?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>
AndroidManifest.xml

運行結果截圖: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;
        }
    }
}
MainActivity.java
<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>
activity_main.xml
<?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>
AndroidManifest.xml

運行結果截圖:下圖是在真實手機上運行的截圖

 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;
    }
}
MainActivity.java
<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>
activity_main.xml
<?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>
AndroidManifest.xml

運行結果截圖:

五:手勢識別
首先,使用系統給出的應用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();
                }
            }
        }
    }
}
MainActivity.java
<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>
activity_main.xml
<?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>
AndroidManifest.xml

運行結果截圖:

能夠支持多筆手勢:須要作以下改動

<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>
activity_main.xml
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();
            }
        }
    }
}
MainActivity.java

多筆手勢監聽方法的測試:

 

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);
        
    }
}
MainActivity.java
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);
    }
}
OtherActivity.java
<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>
activity_main.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="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>
contentview.xml
<?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>
AndroidManifest.xml

運行結果截圖:

 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);
     }
}
MainActivity.java
<?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>
alpha.xml
<?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>
rotate.xml
<?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>
scale.xml
<?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>
translate.xml
<?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>
set.xml
<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>
activity_main.xml
<?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>
AndroidManifest.xml

練習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();
    }
}
MainActivity.java
<?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>
res/drawable下的frame.xml
<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>
activity_main.xml
<?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>
AndroidManifest.xml

運行結果截圖:

 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);
    }
}
MainActivity.java
<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>
activity_main.xml
<?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>
AndroidManifest.xml

運行結果截圖:

十一:圖片的移動和縮放

分析:

練習:

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));
        }
    }
}
MainActivity.java
<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>
activity_mian.xml
<?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>
AndroidManifest.xml

運行結果截圖:

相關文章
相關標籤/搜索