Android TextureView简易教程
如果你想显示一段在线视频或者任意的数据流比如视频或者OpenGL 场景,你可以用android中的TextureView做到。
TextureView的兄弟SurfaceView
应用程序的视频或者opengl内容往往是显示在一个特别的UI控件中:SurfaceView。SurfaceView的工作方式是创建一个置于应用窗口之后的新窗口。这种方式的效率非常高,因为SurfaceView窗口刷新的时候不需要重绘应用程序的窗口(android普通窗口的视图绘制机制是一层一层的,任何一个子元素或者是局部的刷新都会导致整个视图结构全部重绘一次,因此效率非常低下,不过满足普通应用界面的需求还是绰绰有余),但是SurfaceView也有一些非常不便的限制。
因为SurfaceView的内容不在应用窗口上,所以不能使用变换(平移、缩放、旋转等)。也难以放在ListView或者ScrollView中,不能使用UI控件的一些特性比如View.setAlpha()
。
为了解决这个问题 Android 4.0中引入了TextureView。
TextureView
与SurfaceView相比,TextureView并没有创建一个单独的Surface用来绘制,这使得它可以像一般的View一样执行一些变换操作,设置透明度等。另外,Textureview必须在硬件加速开启的窗口中。
TextureView的使用非常简单,你唯一要做的就是获取用于渲染内容的SurfaceTexture。具体做法是先创建TextureView对象,然后实现SurfaceTextureListener接口,代码如下:
private TextureView myTexture;
public class MainActivity extends Activity implements SurfaceTextureListener{
protected void onCreate(Bundle savedInstanceState) {
myTexture = new TextureView(this);
myTexture.setSurfaceTextureListener(this);
setContentView(myTexture);
}
}
Activity implements
了SurfaceTextureListener
接口因此activity中需要重写如下方法:
@Override
public void onSurfaceTextureAvailable(SurfaceTexture arg0, int arg1, int arg2) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture arg0) {
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture arg0, int arg1,int arg2) {
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture arg0) {
}
TextureView可以使用setAlpha和setRotation方法达到改变透明度和旋转的效果。
myTexture.setAlpha(1.0f);
myTexture.setRotation(90.0f);
除了上面的方法之外,TextureView 还有如下方法:
序号 | 方法&描述 |
---|---|
1 | getSurfaceTexture() |
This method returns the SurfaceTexture used by this view. | |
2 | getBitmap(int width, int height) |
This method returns Returns a Bitmap representation of the content of the associated surface texture. | |
3 | getTransform(Matrix transform) |
This method returns the transform associated with this texture view. | |
4 | isOpaque() |
This method indicates whether this View is opaque. | |
5 | lockCanvas() |
This method start editing the pixels in the surface | |
6 | setOpaque(boolean opaque) |
This method indicates whether the content of this TextureView is opaque. | |
7 | setTransform(Matrix transform) |
This method sets the transform to associate with this texture view. | |
8 | unlockCanvasAndPost(Canvas canvas) |
This method finish editing pixels in the surface. | |
例子
下面的例子演示了如何使用TextureView类,我们创建了一个可以在TextureView中预览Camera的demo,可以改变它的角度以及方向。当然程序需要运行在有摄像头的设备上。
下面是MainActivity.java中的代码:
package com.example.textureview;
import java.io.IOException;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.Gravity;
import android.view.Menu;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
import android.view.View;
import android.widget.FrameLayout;
public class MainActivity extends Activity implements SurfaceTextureListener {
private TextureView myTexture;
private Camera mCamera;
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myTexture = new TextureView(this);
myTexture.setSurfaceTextureListener(this);
setContentView(myTexture);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@SuppressLint("NewApi")
@Override
public void onSurfaceTextureAvailable(SurfaceTexture arg0, int arg1,
int arg2) {
mCamera = Camera.open();
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
myTexture.setLayoutParams(new FrameLayout.LayoutParams(
previewSize.width, previewSize.height, Gravity.CENTER));
try {
mCamera.setPreviewTexture(arg0);
} catch (IOException t) {
}
mCamera.startPreview();
myTexture.setAlpha(1.0f);
myTexture.setRotation(90.0f);
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture arg0) {
mCamera.stopPreview();
mCamera.release();
return true;
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture arg0, int arg1,
int arg2) {
// TODO Auto-generated method stub
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture arg0) {
// TODO Auto-generated method stub
}
}
activity_main.xml
<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=".MainActivity" >
<TextureView
android:id="@+id/textureView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.textureview"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.CAMERA"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.textureview.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>
不同参数下的截图:
myTexture.setAlpha(0.5f);
myTexture.setRotation(45.0f);
myTexture.setAlpha(1.5f);
myTexture.setRotation(45.0f);
myTexture.setAlpha(1.0f);
myTexture.setRotation(90.0f);