一、MP3播放器
查看Android API文档可以看到MediaPlayer状态转换图:
练习:
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
运行结果截图:
二:MP4播放器
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
运行结果截图:
三、手机拍照
照相机的一些属性:
预览帧数:preview-frame-rate=30
图片质量:jpeg-thumbnail-quality=90
图片尺寸:preview-size-values=1280x720,800x480,768x432,720x480,640x480,480x320,176x144
SurfaceView只有当activity显示到了前台,该控件才会被创建。
只有当surfaceView被创建了,才把相机所捕获到的数据输出给它。
如果activity回到回台。surfaceview又会被销毁
注意:在拍照的时候相机是被占用的。拍照之后需要重新预览。
练习:
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
运行结果截图:下图是在真实手机上运行的截图
四、视频刻录
查看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
多笔手势监听方法的测试:
八、通知: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
运行结果截图:
九、动画(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
运行结果截图:
十、传感器
练习:
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
运行结果截图: