如果你想顯示一段在線視頻或者任意的數據流比如視頻或者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.setAlpha(1.5f);
myTexture.setAlpha(1.0f);