我们看到市场上视频播放应用在播放视频时,可以在视频上面显示滚动字幕信息,或者其它提示图片信息等.那么它们是如何实现的呢,首先播放视频一般是用SurfaceView,VideoView等,那么我们如何在SurfaceView上显示字幕呢,根据我前面一篇文章所述SurfaceView的工作原理,SurfaceView的生命周期虽然受到它的宿主窗口限制,但是它是工作于不同的窗口,且位于宿主窗口之下.我们直接看个例子.
对应activity_main.xml布局如下:
<FrameLayout 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"> <VideoView android:id="@+id/surface_view" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/toast_info" android:layout_width="600dp" android:layout_height="100dip" android:gravity="center" android:textSize="30sp" android:ellipsize="marquee" android:singleLine="true" android:visibility="gone" /> FrameLayout>
源代码实现如下,下面测试例子实现的功能是播放一个基于rtsp协议的局域网摄像头视频:
public class MainActivity extends Activity { /** Called when the activity is first created. */ private static final String TAG = "zxq"; private Button playButton; private VideoView videoView; private EditText rtspUrl; private TextView mTextInfo; private Handler mHandler = new Handler(); private WindowManager mWindowManager; int index = 0; String [] urlArray = new String[] {"rtsp://10.0.149.217:554/stream1"}; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextInfo = (TextView)this.findViewById(R.id.toast_info); mTextInfo.setTextColor(Color.RED); //mTextInfo.setBackgroundColor(Color.TRANSPARENT); videoView = (VideoView)this.findViewById(R.id.surface_view); videoView.setOnErrorListener(new OnErrorListener() { public boolean onError(MediaPlayer mp, int what, int extra) { return false; } }); videoView.setOnInfoListener(new OnInfoListener() { public boolean onInfo(MediaPlayer mp, int what, int extra) { return true; } }); videoView.setOnPreparedListener(new OnPreparedListener() { public void onPrepared(MediaPlayer mp) { Log.i(TAG, "onPrepared......"); mHandler.postDelayed(new Runnable() { @Override public void run() { mTextInfo.setText("显示字幕中..."); mTextInfo.setVisibility(View.VISIBLE); } }, 5000); //播放器准备5S后开始显示字幕 mHandler.postDelayed(new Runnable() { @Override public void run() { mTextInfo.setVisibility(View.GONE); } }, 60000); //1分钟后隐藏字幕显示 } }); } protected void onResume() { super.onResume(); PlayRtspStream(urlArray[0]); }
private void PlayRtspStream(String rtspUrl){ videoView.setVideoURI(Uri.parse(rtspUrl)); videoView.requestFocus(); videoView.start(); } }
显示效果如下图所示:
另外,有一定要注意布局的选择:
上面的布局如果改成如下
<FrameLayout 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">
<TextView android:id="@+id/toast_info" android:layout_width="600dp" android:layout_height="100dip" android:gravity="center" android:textSize="30sp" android:ellipsize="marquee" android:singleLine="true" android:visibility="gone" />< VideoView android :id= "@+id/surface_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
FrameLayout>
那么是显示不出字幕信息的,由于FrameLayout布局的特点是将其子视图从屏幕左上角一个个叠加上去的,此处就是VideoView会覆盖在TextView上面,如果TextView在VideoView下面,那么VideoView是无法"挖洞"来显示其下面的视图内容的.当然也可以用其它布局例如RelativeLayout来设计.