一、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

运行结果截图:

java攻城狮之路(Android篇)--MP3 MP4、拍照、国际化、样式主题、图片移动和缩放的更多相关文章

  1. java攻城狮之路(Android篇)--BroadcastReceiver&Service

    四大组件:activity 显示. contentProvider 对外暴露自己的数据给其他的应用程序.BroadcastReceiver 广播接收者,必须指定要接收的广播类型.必须明确的指定acti ...

  2. java攻城狮之路(Android篇)--Activity生命

    一:Activity的激活 1.写一个类 extends Activity Activity是android的四大组件之一.Activity的激活分为显式意图激活和隐式意图激活.如果一个activit ...

  3. java攻城狮之路(Android篇)--ListView与ContentProvider

    一.ListView 1.三种Adapter构建ListView ListView添加条目的时候, 可以使用setAdapter(ListAdapter)方法, 常用的ListAdapter有三种 B ...

  4. java攻城狮之路(Android篇)--widget_webview_metadata_popupwindow_tabhost_分页加载数据_菜单

    一.widget:桌面小控件1 写一个类extends AppWidgetProvider 2 在清单文件件中注册: <receiver android:name=".ExampleA ...

  5. java攻城狮之路(Android篇)--与服务器交互

    一.图片查看器和网页源码查看器 在输入地址的是不能输入127.0.0.1 或者是 localhost.ScrollView :可以看成一个滚轴 可以去包裹很多的控件在里面 练习1(图片查看器): pa ...

  6. java攻城狮之路(Android篇)--SQLite

    一.Junit    1.怎么使用        在AndroidManifest.xml文件中进行配置, 在manifest借点下配置instrumentation, 在application借点下 ...

  7. java攻城师之路(Android篇)--搭建开发环境、拨打电话、发送短信、布局例子

    一.搭建开发环境 1.所需资源 JDK6以上 Eclipse3.6以上 SDK17, 2.3.3 ADT17 2.安装注意事项 不要使用中文路径 如果模拟器默认路径包含中文, 可以设置android_ ...

  8. java攻城狮之路--复习xml&dom_pull编程续

    本章节我们要学习XML三种解析方式: 1.JAXP DOM 解析2.JAXP SAX 解析3.XML PULL 进行 STAX 解析 XML 技术主要企业应用1.存储和传输数据 2.作为框架的配置文件 ...

  9. java攻城狮之路--复习xml&dom_pull编程

    xml&dom_pull编程: 1.去掉欢迎弹窗界面:在window项的preferences选项中输入“configuration center” 找到这一项然后     把复选框勾去即可. ...

随机推荐

  1. linux学习笔记1

    2016年09月25日 unix与linux发展史 unix是linux之父,学习linux后能容易上手unix. linux是源码开放的unix,由一位芬兰大学生李纳斯在网络上发起,和后来众多爱好者 ...

  2. paip.提升性能----数据库连接池以及线程池以及对象池

    paip.提升性能----数据库连接池以及线程池以及对象池 目录:数据库连接池c3po,线程池ExecutorService:Jakartacommons-pool对象池 作者Attilax  艾龙, ...

  3. 理解Certificate、App Id、Identifiers 和 Provisioning Profile

    做真机测试的时候,按照网上的流程,走通了,当时没有注意各种证书等的意思.现在做消息推送,需要各种证书.APP ID信息,为了更好的理解这个过程,所以整理了网上关于证书等的相关资料.方便自己和有需要的朋 ...

  4. iOS-项目打包为ipa文件

    最近自己做的一个项目,由于app store发布流程比较复杂,且审核周期较长,客户希望提前能看到产品,所以我先给自己的项目打包成一个ipa文件(类似Android的apk安装包),然后发布在" ...

  5. Leetcode 344 Reverse String 字符串处理

    题意:反转字符串,用好库函数. class Solution { public: string reverseString(string s) { reverse(s.begin(),s.end()) ...

  6. Android 实用工具Hierarchy Viewer实战

    在Android的SDK工具包中,有很多十分有用的工具,可以帮助程序员开发和测试Android应用程序,大大提高其工作效率.其中的一款叫Hierachy Viewer的可视化调试工具,可以很方便地在开 ...

  7. Hello.class所在路径下, 输入命令:java Hello.class,会出现什么结果,为什么?

    所在路径下, 输入命令:java Hello.class: 因为DOS没有规定路径,所有么有在默认路径下找到Hello.class文件,导致提示 错误: 找不到或无法加载主类 Hello.class.

  8. jmap命令(Java Memory Map)(转)

    JDK内置工具使用 一.javah命令(C Header and Stub File Generator) 二.jps命令(Java Virtual Machine Process Status To ...

  9. vs2012 MSDN帮助文档离线包下载安装方法

    vs2012安装文件 自带的 MSDN帮助文档不全, 需要自己手动添加需要的离线文档包, 具体方法如下 1. 打开 vs2012 2. 按 ctrl + alt + F1 打开帮助文档管理器 3. 在 ...

  10. solr课程学习系列-solr的概念与结构(1)

    Solr是基于Lucene的采用Java5开发的一个高性能全文搜索服务器.源于lucene,却更比Lucene更为丰富更为强大的查询语言.同时实现了可配置.可扩展并对查询性能进行了优化,并且提供了一个 ...