GVKun编程网logo

Android 实现视频字幕Subtitle和横竖屏切换示例(android视频播放横竖屏切换)

15

如果您想了解Android实现视频字幕Subtitle和横竖屏切换示例的相关知识,那么本文是一篇不可错过的文章,我们将对android视频播放横竖屏切换进行全面详尽的解释,并且为您提供关于Androi

如果您想了解Android 实现视频字幕Subtitle和横竖屏切换示例的相关知识,那么本文是一篇不可错过的文章,我们将对android视频播放横竖屏切换进行全面详尽的解释,并且为您提供关于Android Activity 横竖屏切换的生命周期、Android Activity横竖屏切换生命周期详解、android 中禁止横竖屏切换、Android 如何只禁止某一个Layout在横竖屏切换的时候重新加载的有价值的信息。

本文目录一览:

Android 实现视频字幕Subtitle和横竖屏切换示例(android视频播放横竖屏切换)

Android 实现视频字幕Subtitle和横竖屏切换示例(android视频播放横竖屏切换)

系统自带的VideoView有些视频格式不支持,那么我们可以用第三方实现的VideoView替代系统的来播放视频,比较流行的有ijkplayer、vitamio。

最近有个需求就是需要给视频添加字幕,其实也挺简单的。字幕比较常用的格式是srt,实际它就是文本,把它解析出来,然后根据时间再展示就OK。还有就是实现了即使旋转按钮关闭,根据方向感应器也能做到横竖屏切换。

本文用的是系统VideoView,然后播放sd卡中的视频来作为演示(源码中带有f2.mp4和f2.srt,运行时拷贝到sd卡就行)。下面简单介绍一下源码:

MainActivity包括显示字幕和如何实现横竖屏如何切换:

public class SubtitleActivity extends Activity implements View.OnClickListener,OnTouchListener{
	private VideoView videoView ;
	TextView tvSrt,mCurrentTime,mTotalTime,resolution_switch,mediacontroller_file_name;
	ImageView mediacontroller_play_pause,switch_screen;
	private SeekBar progress_seekbar;
	private AudioManager mAM;
	private long totalDuration;
	private boolean mShowing = true,mDragging,isResolution;
	private static final int PARSE_SRT = 0;
	private static final int FADE_OUT = 1;
	private static final int SHOW_PROGRESS = 2;
	private static final int CHANGE_VIDEOVIEW_BG = 3;
	private static final int SCREEN_ORIENTATION_USER = 4;
	private static final int sDefaultTimeout = 3000;
	private RelativeLayout videoview_layout,mMediaController;
	private ListView resolution_listview;
	private boolean isPortraint = true;
	private static int LockScreen = -1;// 用于记录是否关闭屏幕旋转,0为关闭1为开启
	private int screenWidth,videoViewHeight;
	List<VideoPathObject> videopathList=new ArrayList<VideoPathObject>();
	Handler mHandler=new Handler(){
		public void handleMessage(Message msg){
			long pos;
			switch (msg.what) {
				case PARSE_SRT:
					SrtParser.showSRT(videoView,tvSrt) ;
				//每隔500ms执行一次showSRT(),根据时间匹配显示哪句字幕
					mHandler.sendEmptyMessageDelayed(0,500);
					break;
				case FADE_OUT:
					showOrHideController();
					break;
				case SHOW_PROGRESS:
					pos = setControllerProgress();
					if (!mDragging && mShowing) {
						msg = obtainMessage(SHOW_PROGRESS);
					sendMessageDelayed(msg,1000 - (pos % 1000));
					}
					break;
				case CHANGE_VIDEOVIEW_BG:
					videoView.setBackgroundColor(0x00000000);
					break;
			}
		}
	};
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_subtitle);
		videoView = (VideoView)this.findViewById(R.id.videoView );
		mAM = (AudioManager) getSystemService(Context.AUdio_SERVICE);
		screenWidth = APPApplication.screenWidth;
		videoViewHeight = screenWidth * 9 / 16;
		tvSrt = (TextView)findViewById(R.id.srt);//项目中显示字幕的控件
	mediacontroller_file_name= (TextView)findViewById(R.id.mediacontroller_file_name);
//		String[]splitStr=Constant.videoUrl1.split("/");
//		mediacontroller_file_name.setText(splitStr[splitStr.length-1]);
		mTotalTime = (TextView) findViewById(R.id.mediacontroller_time_total);
		mCurrentTime = (TextView) findViewById(R.id.mediacontroller_time_current);
		resolution_switch = (TextView) findViewById(R.id.resolution_switch);
	mediacontroller_play_pause = (ImageView) findViewById(R.id.mediacontroller_play_pause);
		switch_screen = (ImageView) findViewById(R.id.switch_screen);
		videoview_layout = (RelativeLayout) findViewById(R.id.videoview_layout);
		mediacontroller_play_pause.setonClickListener(this);
		progress_seekbar = (SeekBar) findViewById(R.id.mediacontroller_seekbar);
		videoview_layout = (RelativeLayout) findViewById(R.id.videoview_layout);
		mMediaController = (RelativeLayout) findViewById(R.id.media_controller);
		resolution_listview = (ListView) findViewById(R.id.resolution_listview);
		resolution_switch.setonClickListener(this);
		videoView.setonTouchListener(this);
		progress_seekbar.setonSeekBarchangelistener(mSeekListener);
		LayoutParams params = new RelativeLayout.LayoutParams(
				LayoutParams.MATCH_PARENT,videoViewHeight);
		videoview_layout.setLayoutParams(params);
		try {
	// 1代表开启自动旋转true,0代表未开启自动旋转false
	// Settings.System.getInt(mContext.getContentResolver(),Settings.System.ACCELEROMETER_ROTATION,0);
		LockScreen = Settings.System.getInt(getContentResolver(),Settings.System.ACCELEROMETER_ROTATION);
		} catch (SettingNotFoundException e) {
			// Todo Auto-generated catch block
			e.printstacktrace();
		}
//		String rawUri = "android.resource://" + getPackageName() + "/" + R.raw.renwei;
		Uri uri = Uri.parse(Constant.videoUrl1);
		//设置视频控制器
// videoView.setMediaController(new MediaController(this));
		//播放完成回调
		videoView.setonCompletionListener( new MyPlayerOnCompletionListener());
		videoView.setonPreparedListener(new OnPreparedListener() {
			//@Override
			public void onPrepared(MediaPlayer mp) {
				totalDuration=videoView.getDuration();
				if (mTotalTime != null)
			mTotalTime.setText("/"+generateTime(totalDuration));
			}
		});
		//设置视频路径
		videoView.setVideoURI(uri);
		//开始播放视频
		videoView.start();
		SrtParser.parseSrt(this);
		SrtParser.showSRT(videoView,tvSrt) ;
		mHandler.sendEmptyMessageDelayed(0,500);
		initVideoResolution();
	}
	private void initVideoResolution(){
		VideoPathObject object1=new VideoPathObject();
		object1.videoStatus="超清";
		videopathList.add(object1);
		VideoPathObject object2=new VideoPathObject();
		object2.videoStatus="高清";
		videopathList.add(object2);
		VideoPathObject object3=new VideoPathObject();
		object3.videoStatus="标清";
		videopathList.add(object3);
		switchResolution(videopathList);
	}
	class MyPlayerOnCompletionListener implements MediaPlayer.OnCompletionListener {
		@Override
		public void onCompletion(MediaPlayer mp) {
	Toast.makeText( SubtitleActivity.this,"播放完成了",Toast.LENGTH_SHORT).show();
		}
	}
	private OnSeekBarchangelistener mSeekListener = new OnSeekBarchangelistener() {
		public void onStartTrackingTouch(SeekBar bar) {
			mDragging = true;
			mHandler.removeMessages(SHOW_PROGRESS);
			mAM.setStreamMute(AudioManager.STREAM_MUSIC,true);
		}
		public void onProgressChanged(SeekBar bar,int progress,boolean fromuser) {
			if (!fromuser)
				return;
			int newposition = (int)(totalDuration * progress) / 1000;
			String time = generateTime(newposition);
			videoView.seekTo(newposition);
			mCurrentTime.setText(time);
		}
		public void onStopTrackingTouch(SeekBar bar) {
			videoView.seekTo(((int)totalDuration * bar.getProgress()) / 1000);
			hideMediaController(sDefaultTimeout);
			mAM.setStreamMute(AudioManager.STREAM_MUSIC,false);
			mDragging = false;
			mHandler.sendEmptyMessageDelayed(SHOW_PROGRESS,1000);
		}
	};
	private void switchResolution(final List<VideoPathObject> videopathList) {
		resolution_switch
	.setText(videopathList.get(videopathList.size() - 1).videoStatus);
		mediacontroller_play_pause.setimageResource(R.drawable.player_play);
		final ResolutionAdapter adapter = new ResolutionAdapter(videopathList,SubtitleActivity.this);
		resolution_listview.setAdapter(adapter);
		resolution_listview
		.setonItemClickListener(new AdapterView.OnItemClickListener() {
		@Override
			public void onItemClick(AdapterView<?> arg0,View arg1,int position,long arg3) {
				// Todo Auto-generated method stub
//				// currentPosition = videoView.getCurrentPosition();
//				currentPosition = videoView.getCurrentPosition();
//				Log.d("gaolei","currentPosition---------1------"
//								+ currentPosition);
				VideoPathObject pathObject = videopathList
								.get(position);
////				playVideo(pathObject.videoUrl);
//				adapter.changePosition(position);
				resolution_switch.setText(pathObject.videoStatus);
				resolution_listview.setVisibility(View.GONE);
					}
				});
	}
	public void showOrHideController() {
		if (mShowing) {
			mHandler.removeMessages(SHOW_PROGRESS);
			mHandler.removeMessages(FADE_OUT);
			mMediaController.setVisibility(View.GONE);
			resolution_listview.setVisibility(View.GONE);
			mShowing = false;
		} else {
			mHandler.sendEmptyMessage(SHOW_PROGRESS);
			mMediaController.setVisibility(View.VISIBLE);
			hideMediaController(sDefaultTimeout);
			mShowing = true;
		}
	}
	public void hideMediaController(int sDefaultTimeout) {
		mHandler.sendEmptyMessageDelayed(FADE_OUT,sDefaultTimeout);
	}
	private long setControllerProgress() {
		if (videoView == null || mDragging)
			return 0;
		int position = videoView.getCurrentPosition();
		if (progress_seekbar != null) {
			if (totalDuration > 0) {
				long pos = 1000L * position / totalDuration;
				// Log.d("gaolei","progress--------------" + pos);
				progress_seekbar.setProgress((int) pos);
			}
			int percent = videoView.getBufferPercentage();
			progress_seekbar.setSecondaryProgress(percent * 10);
		}
		if (mCurrentTime != null)
			mCurrentTime.setText(generateTime(position));
		return position;
	}
	private static String generateTime(long position) {
		int totalSeconds = (int) (position / 1000);
		int seconds = totalSeconds % 60;
		int minutes = (totalSeconds / 60) % 60;
		int hours = totalSeconds / 3600;
		if (hours > 0) {
			return String.format(Locale.US,"%02d:%02d:%02d",hours,minutes,seconds).toString();
		} else {
			return String.format(Locale.US,"%02d:%02d",seconds)
					.toString();
		}
	}
	private void updatePausePlay() {
		if (videoView.isPlaying()) {
			videoView.pause();
			mediacontroller_play_pause
					.setimageResource(R.drawable.player_pause);
		} else {
			videoView.start();
			mediacontroller_play_pause.setimageResource(R.drawable.player_play);
		}
	}
	public void showResolution(View view) {
		if (!isResolution) {
			resolution_listview.setVisibility(View.VISIBLE);
			isResolution = true;
		} else {
			resolution_listview.setVisibility(View.GONE);
			isResolution = false;
		}
	}
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
		if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
			changetoFullScreen();
			Log.d("gaolei","ORIENTATION_LANDSCAPE-------------");
		}
		if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
			changetoSmallScreen();
			Log.d("gaolei","ORIENTATION_PORTRAIT-------------");
		}
	}
	public void switchScreen(View view) {
		if (isPortraint) {
			handToFullScreen();
		} else {
			handToSmallScreen();
		}
	}
	public void handToSmallScreen() {
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
		changetoSmallScreen();
		/**
		 * 这里点击按钮转屏,用户5秒内不转屏幕,将自动识别当前屏幕方向
		 */
		autoSwitchScreenorientation();
	}
	public void handToFullScreen() {
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
		changetoFullScreen();
		autoSwitchScreenorientation();
	}
	private void changetoFullScreen() {
		isPortraint = false;
		LayoutParams params = new RelativeLayout.LayoutParams(
				LayoutParams.MATCH_PARENT,APPApplication.screenWidth);
		videoview_layout.setLayoutParams(params);
		videoView.setLayoutParams(params);
		WindowManager.LayoutParams windowparams = getwindow().getAttributes();
		windowparams.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
		getwindow().setAttributes(windowparams);
		getwindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
		switch_screen.setimageResource(R.drawable.player_switch_small);
	}
	private void changetoSmallScreen() {
		isPortraint = true;
		LayoutParams params = new RelativeLayout.LayoutParams(
				LayoutParams.MATCH_PARENT,videoViewHeight);
		videoview_layout.setLayoutParams(params);
		videoView.setLayoutParams(params);
		WindowManager.LayoutParams windowparams = getwindow().getAttributes();
		windowparams.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN);
		getwindow().setAttributes(windowparams);
		getwindow()
				.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
		switch_screen.setimageResource(R.drawable.player_switch_big);
	}
	public void autoSwitchScreenorientation() {
//		手动旋转屏幕,5s后会执行感应的方向
		new Timer().schedule(new TimerTask() {
			@Override
			public void run() {
			// Todo Auto-generated method stub
			setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
			Log.d("gaolei","SCREEN_ORIENTATION_FULL_SENSOR");				}
		},5000);
	}
	@Override
	public boolean onTouch(View v,MotionEvent event) {
		// Todo Auto-generated method stub
		switch (event.getAction()) {
			case MotionEvent.ACTION_DOWN: {
				showOrHideController();
				break;
			}
		}
		return false;
	}
	@Override
	public void onClick(View view) {
		// Todo Auto-generated method stub
		switch(view.getId()){
			case R.id.mediacontroller_play_pause:
				Log.d("gaolei","mediacontroller_play_pause");
				updatePausePlay();
				break;
			case R.id.resolution_switch:
				resolution_listview.setVisibility(View.VISIBLE);
				break;
		}
	}
	public void jumpToMain(View view){
		startActivity(new Intent(this,MainActivity.class));
	}
	public void onRestart(){
		super.onRestart();
		videoView.start();
		mediacontroller_play_pause.setimageResource(R.drawable.player_play);
	}
	public void onStop(){
		super.onStop();
		videoView.pause();
		mediacontroller_play_pause.setimageResource(R.drawable.player_pause);
	}
}

SrtParser就是解析字幕文件的算法:

public class SrtParser {
 public static ArrayList<SRT>srtList;
 public static int lastEndTime;
 /**
 * 解析SRT字幕文件
 * 字幕路径
 */
 public static void parseSrt(Context context) {
 InputStream inputStream = null;
 try {
//  inputStream=context.getResources().openRawResource(R.raw.renwei2);
  inputStream = new FileInputStream(Constant.srtUrl1);
  // Todo Auto-generated catch block
  BufferedReader br = new BufferedReader(new InputStreamReader(
   inputStream,"GB2312"));
  String line = null;
  srtList = new ArrayList<SRT>();
  StringBuffer sb = new StringBuffer();
  while ((line = br.readLine()) != null) {
  // Log.d("gaolei","br.readLine()-----------"+br.readLine());
  if (!line.equals("")) {
   Log.d("gaolei","line-------------------"+ line);
   sb.append(line).append("@");
   continue;
  }
  Log.d("gaolei","sb.toString()-----------"+sb.toString());
  String[] parseStrs = sb.toString().split("@");
  // 该if为了适应一开始就有空行以及其他不符格式的空行情况
  if (parseStrs.length < 3) {
   sb.delete(0,sb.length());// 清空,否则影响下一个字幕元素的解析</i>
   continue;
  }
  SRT srt = new SRT();
  // 解析开始和结束时间
  String timetotime = parseStrs[1];
  int begin_hour = Integer.parseInt(timetotime.substring(0,2));
  int begin_mintue = Integer.parseInt(timetotime.substring(3,5));
  int begin_scend = Integer.parseInt(timetotime.substring(6,8));
  int begin_milli = Integer.parseInt(timetotime.substring(9,12));
  int beginTime = (begin_hour * 3600 + begin_mintue * 60 + begin_scend)
   * 1000 + begin_milli;
  int end_hour = Integer.parseInt(timetotime.substring(17,19));
  int end_mintue = Integer.parseInt(timetotime.substring(20,22));
  int end_scend = Integer.parseInt(timetotime.substring(23,25));
  int end_milli = Integer.parseInt(timetotime.substring(26,29));
  int endTime = (end_hour * 3600 + end_mintue * 60 + end_scend)
   * 1000 + end_milli;
  System.out.println("开始:" + begin_hour + ":" + begin_mintue +
   ":"
   + begin_scend + ":" + begin_milli + "=" + beginTime
   + "ms");
  System.out.println("结束:" + end_hour + ":" + end_mintue + ":"
   + end_scend + ":" + end_milli + "=" + endTime + "ms");
  // 解析字幕文字
  String srtBody = "";
  // 可能1句字幕,也可能2句及以上。
  for (int i = 2; i < parseStrs.length; i++) {
   srtBody += parseStrs[i]+ "\n";
  }
  // 删除最后一个"\n"
  srtBody = srtBody.substring(0,srtBody.length() - 1);
  // 设置SRT
  srt.setBeginTime(beginTime);
  srt.setEndTime(endTime);
  srt.setSrtBody(new String(srtBody.getBytes(),"UTF-8"));
  srtList.add(srt);
  sb.delete(0,sb.length());// 清空,否则影响下一个字幕元素的解析
  }
  lastEndTime=srtList.get(srtList.size()-1).getEndTime();
  br.close();
 } catch (IOException e) {
  // Todo Auto-generated catch block
  e.printstacktrace();
 }
 //每隔500ms执行一次()取
 }
 public static void showSRT(VideoView videoView,TextView tvSrt) {
// 	Log.d("gaolei","srt_map.size()--------------"+srt_map.size());
 int currentPosition = videoView.getCurrentPosition();//vv是VideoView播放器
 if(currentPosition>lastEndTime){
  tvSrt.setVisibility(View.GONE);
  return;
 }
 for(int i=0;i<srtList.size();i++){
  SRT srtbean =srtList.get(i);
  if (currentPosition > srtbean.getBeginTime()
   && currentPosition < srtbean.getEndTime()) {
  tvSrt.setText(srtbean.getSrtBody());
  //显示过的就删掉,提高查询效率
  srtList.remove(i);
  break;//找到后就没必要继续遍历下去,节约资源
  }
 }
 }
}

运行效果图:

项目源码,点击下载......

以上这篇Android 实现视频字幕Subtitle和横竖屏切换示例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持编程小技巧。

您可能感兴趣的文章:

  • Android实现横竖屏切换的实例代码
  • android实现在横竖屏切换时页面信息不被重置的示例分享
  • Android 屏幕横竖切换详解
  • Android实现屏幕旋转方法总结
  • 解决Android手机屏幕横竖屏切换
  • 解析Android横竖屏切换的问题

Android Activity 横竖屏切换的生命周期

Android Activity 横竖屏切换的生命周期

前言

在开发中常要处理横竖屏切换,怎么处理先看生命周期

申明

Activity 横竖屏切换时需要回调两个函数 ,所以在此将这个两个函数暂时看成是Activity 横竖屏切换的生命周期的一部分,这两个函数如下

onSaveInstanceState(Bundle outState) :Activity 即将销毁时保存数据
onRestoreInstanceState(Bundle savedInstanceState) : Activity 重建或者恢复时候取出数据

横竖屏切换生命周期

1、启动程序进入Activity界面

2、

2、旋转屏幕

3、再次旋转屏幕

4 在AndroidManifest.xml中设置

android:configChanges="orientation|screenSize",切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法

注意:

MiniSdkVersion大于等于 13 时候:android:configChanges="orientation" 或者 android:configChanges="orientation|keyboardHidden" 重新调用各个生命周期

MiniSdkVersion小于 13 时候:

(1)不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次

(2)设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次

(3)设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法

5、屏幕切换避免,重走Activity生命周期

从上面屏幕切换生命周期可以看出每次切换都在重新创建,为了不必要的麻烦比如视频播放屏幕旋转等,避免重走生命周期就是一个比较好的解决方案

(1)android 2.3之前的版本 android:configChanges="orientation|keyboardHidden"

(2)android 3.0之后的版本 android:configChanges="orientation|screenSize"

横竖屏设置

Android横竖屏切换在手机开发中比较常见,很多软件在开发过程中为了避免横竖屏切换时引发不必要的麻烦,通常禁止掉横竖屏的切换。

一、在AndroidManifest.xml中设置activity中的android:screenorientation属性值来实现。

(1)竖屏:android:screenorientation="portrait"

(2)横屏:android:screenorientation="landscape"

二、在Java代码中通过类似如下代码来设置 (不推荐这种方法,在大的app不同方向启动时会慢)

(1)竖屏: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)

(2)横屏:setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)

三、如果要彻底禁止翻转,忽略重力感应带来的切换,(模拟器上不管用,在真机上是正确的)

(1)忽略重力:android:screenorientation="nosensor"

横竖屏辨识

一、在onConfigurationChanged里判断,为了onConfigurationChanged在监听屏幕方向变化有效需要以下条件

(1)AndroidManifest.xml增加权限:<uses-permission android:name="android.permission.CHANGE_CONfigURATION"></uses-permission>

(2)AndroidManifest.xml里设置的MiniSdkVersion和 TargetSdkVersion属性大于等于13

(3)在AndroidManifest.xml的Activity里增加:android:configChanges="keyboard|screenSize|orientation|layoutDirection"

(4)在onConfigurationChanged(Configuration newConfig)进行判断

@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if(newConfig.orientation == 1)//竖屏 
if(newConfig.orientation == 2)// 横屏
}

二、因为当屏幕变为横屏的时候,系统会重调用Activity的onCreate方法可以在onCreate中来检查当前的方向,然后可以让你的setContentView来载入不同的layout xml。

if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
Log.i("info","landscape"); // 横屏
} else if(this.getResources().getConfiguration().orientation ==Configuration.ORIENTATION_PORTRAIT) {
Log.i("info","portrait"); // 竖屏
}

注意:该方法是在AndroidManifest.xml中不设置onConfigurationChanged才能重走生命周期

横竖屏切换布局文件设置

如果要让软件在横竖屏之间切换,由于横竖屏的高宽会发生转换,有可能会要求不同的布局。可以通过以下方法来切换布局

(1)在res目录下建立layout-land和layout-port目录,相应的layout文件名称不变,比如main.xml。layout-land是横屏的layout,layout-port是竖屏的layout,其他的不用管,模拟器会自动寻找。

(2)在上面横竖屏辨识中,如果横竖屏出现变化,在onCreate()或者onConfigurationChanged()判断方向,就可以在相应的方法中重新setContentView来载入不同的layout xml布局文件

横竖屏切换数据保存与读取

另外,android中每次屏幕的切换动会重启Activity,所以应该在Activity销毁前保存当前活动的状态,在Activity再次Create的时候载入配置,那样,进行中的游戏就不会自动重启了!

Activity 数据保存

(1)如果因为系统资源紧张而导致Activity的Destory或者旋转屏幕时被destroyed与Recreated, 系统会在用户回到这个Activity时有这个Activity存在过的记录,系统会使用那些保存的记录数据(instance state)它是一些存放在Bundle对象中的key-value pairs,系统默认使用 Bundle保存信息

(2)为了可以保存额外更多的数据到instance state,要重写写这个回调函数onSaveInstanceState(Bundle outState),系统会在Activity被异常Destory时传递Bundle对象,这样我们就可以增加额外的信息到Bundle中并保存到系统中。若系统在Activity被Destory之后想重新创建这个Activity实例时,之前的Bundle对象会(系统)被传递到你我们activity的

(3)Activity开始stop,系统会调用 onSaveInstanceState(Bundle outState) ,Activity可以用键值对的集合来保存状态信息。这个方法会默认保存Activity视图的状态信息,如在 EditText组件中的文本或 ListView 的滑动位置

Activity 数据恢复

(1)当Activity从Destory中重建,我们可以从系统传递的Activity的Bundle中恢复保存的状态。 onCreate() 与 onRestoreInstanceState() 回调方法都接收到了同样的Bundle,里面包含了同样的实例状态信息。

(2)由于 onCreate() 方法会在第一次创建新的Activity实例与重新创建之前被Destory的实例时都被调用,我们必须在尝试读取 Bundle 对象前检测它是否为null。如果它为null,系统则是创建一个新的Activity实例,而不是恢复之前被Destory的Activity。

(3)也可以选择实现 onRestoreInstanceState() ,而不是在onCreate方法里面恢复数据。 onRestoreInstanceState()方法会在 onStart() 方法之后执行. 系统仅仅会在存在需要恢复的状态信息时才会调用 onRestoreInstanceState() ,因此不需要检查 Bundle 是否为null。

以上所述是小编给大家介绍的Android Activity 横竖屏切换的生命周期的相关知识,希望对大家有所帮助!

Android Activity横竖屏切换生命周期详解

Android Activity横竖屏切换生命周期详解

关于Activity生命周期和横竖屏切换时,生命周期的执行过程,网上有很多文章。但是都写的很模糊,并且不完善。一般的我们去切换屏幕方向都是不希望Activity被重新创建,这时就需要对一些属性进行设置,或者使用代码设置。文章通过以上方面解析Activity在横竖屏切换时,生命周期方法执行过程。

  • 1.Activity生命周期

  • 2.configChanges属性解析

  • 3.orientation属性

  • 4.keyboardHidden属性

  • 5.screenSize属性

  • 6.总结

  • activity生命周期方法
    默认情况下,activity从创建到销毁会执行以下生命周期方法

onCreate -->onStart–>onResumeo -->nPause -->onStop -->onDestroy

  • configChanges属性详解

1.orientation 屏幕在纵向和横向间旋转
2.keyboardHidden 键盘显示或隐藏
3.screenSize 屏幕大小改变了
4.fontScale 用户变更了首选的字体大小
5.locale 用户选择了不同的语言设定
6.keyboard 键盘类型变更,例如手机从12键盘切换到全键盘
7.touchscreen或navigation 键盘或导航方式变化,一般不会发生这样的事件
常用的包括:orientation keyboardHidden screenSize,设置这三项界面不会走Activity的生命周期,只会回调onConfigurationChanged方法。

  • screenorientation属性详解

1.unspecified 默认值,由系统判断状态自动切换
2.landscape 横屏
3. portrait 竖屏
4.user 用户当前设置的orientation值
5. behind 下一个要显示的Activity的orientation值
6. sensor 使用传感器 传感器的方向
7. nosensor 不使用传感器 基本等同于unspecified 仅landscape和portrait常用,代表界面默认是横屏或者竖屏,还可以再代码中更改。

1.AndroidManifest没有设置configChanges属性

  • 竖屏启动: onCreate -->onStart–>onResume
  • 切换横屏: onPause -->onSaveInstanceState -->onStop -->onDestroy -->onCreate–>onStart --> onRestoreInstanceState–>onResume -->onPause -->onStop -->onDestroy
  • 横屏启动: onCreate -->onStart–>onResume
  • 切换竖屏: onPause -->onSaveInstanceState -->onStop -->onDestroy -->onCreate–>onStart --> onRestoreInstanceState–>onResume -->onPause -->onStop -->onDestroy

2.AndroidManifest设置了configChanges android:configChanges=“orientation”

  • 竖屏启动: onCreate -->onStart–>onResume
  • 切换横屏: onPause -->onSaveInstanceState -->onStop -->onDestroy -->onCreate–>onStart --> onRestoreInstanceState–>onResume -->onPause -->onStop -->onDestroy
  • 横屏启动: onCreate -->onStart–>onResume
  • 切换竖屏: onPause -->onSaveInstanceState -->onStop -->onDestroy -->onCreate–>onStart --> onRestoreInstanceState–> onResume -->onPause -->onStop -->onDestroy

3.AndroidManifest设置了configChanges android:configChanges=“orientation|keyboardHidden|screenSize”

  • 竖(横)屏启动:onCreate -->onStart–>onResume
  • 切换横(竖)屏:onConfigurationChanged (Android 6.0 Android 7.0 Android 8.0)

4.AndroidManifest设置了configChanges android:configChanges=“orientation|screenSize”

  • 竖(横)屏启动:onCreate -->onStart–>onResume
  • 切换横(竖)屏:onConfigurationChanged (Android 6.0 Android 7.0 Android 8.0)
  • 注意:代码动态设置横竖屏状态(onConfigurationChanged当屏幕发生变化的时候回调)

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

  • 总结
    1.没有设置configChanges属性,当前的界面调用onSaveInstanceState走一遍流程,然后重启调用onRestoreInstanceState再走一遍完整流程,最终destory。
    2.设置了configChanges属性为orientation之后,Android6.0 同没有设置configChanges情况相同,完整的走完了两个生命周期,调用了onSaveInstanceState和onRestoreInstanceState方法;Android 7.0则会先回调onConfigurationChanged方法,剩下的流程跟Android 6.0 保持一致;Android 8.0 系统更是简单,
    只是回调了onConfigurationChanged方法,并没有走Activity的生命周期方法。
    3.设置android:configChanges=“orientation|keyboardHidden|screenSize” 则都不会调用Activity的其他生命周期方法,只会调用onConfigurationChanged方法。
    4.没有了keyboardHidden跟3是相同的,orientation代表横竖屏切换 screenSize代表屏幕大小发生了改变,
    设置了这两项就不会回调Activity的生命周期的方法,只会回调onConfigurationChanged 。

Jaynm 发布了11 篇原创文章 · 获赞 30 · 访问量 9万+ 私信 关注

android 中禁止横竖屏切换

android 中禁止横竖屏切换

在 Android 中要让一个程序的界面始终保持一个方向,不随手机方向转动而变化的办法: 只要在 AndroidManifest.xml 里面配置一下就可以了。

在 AndroidManifest.xml 的 activity (需要禁止转向的 activity) 配置中加入 android:screenOrientation=”landscape” 属性即可 (landscape 是横向,portrait 是纵向)。例如:
Java 代码

1. <application android:persistent="true" 
2.       android:label="@string/home_title" 
3.       android:icon="@drawable/ic_launcher_home"> 
4.  
5.     <activity android:name="Home" 
6.             android:theme="@style/Theme" 
7.             android:launchMode="singleInstance" 
8.             android:stateNotNeeded="true" 
9.             android:screenOrientation="portrait"> 
10.         <intent-filter> 
11.             <action android:name="android.intent.action.MAIN" /> 
12.             <category android:name="android.intent.category.HOME"/> 
13.             <category android:name="android.intent.category.DEFAULT" /> 
14.         </intent-filter> 
15.     </activity> 

<application android:persistent="true"
android:label="@string/home_title"
android:icon="@drawable/ic_launcher_home">

<activity android:name="Home"
android:theme="@style/Theme"
android:launchMode="singleInstance"
android:stateNotNeeded="true"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>


另外,android 中每次屏幕方向切换时都会重启 Activity,所以应该在 Activity 销毁前保存当前活动的状态,在 Activity 再次 Create 的时候载入配置,那样,进行中的游戏就不会自动重启了!

要避免在转屏时重启 activity,可以通过在 androidmanifest.xml 文件中重新定义方向 (给每个 activity 加上 android:configChanges=”keyboardHidden|orientation” 属性),并根据 Activity 的重写 onConfigurationChanged (Configuration newConfig) 方法来控制,这样在转屏时就不会重启 activity 了,而是会去调用 onConfigurationChanged (Configuration newConfig) 这个钩子方法。例如:

Java 代码

1. if(newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE){ 
2.   // 横向  
3.   setContentView(R.layout.file_list_landscape);  
4. }else{ 
5.   // 竖向  
6.    setContentView(R.layout.file_list);  
7. } 

if(newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE){
// 横向
setContentView(R.layout.file_list_landscape);
}else{
// 竖向
setContentView(R.layout.file_list);
}


在模拟器中,要使程序转屏可以使用快捷键 F12 或 Ctrl+F11 来切换。当然在用命令行启动模拟器时可以直接使用参数 emulator.exe -skin HVGA-L 来启动横屏的程序。

 

android 禁止横竖屏切换时调用 onCreate 函数
2011-08-04 18:04 385 人阅读 评论 (0) 收藏 举报
在横竖屏切换的时候会重新调用 onCreate 方法,可以使用以下方法禁止切换的过程中调用 onCreate 方法,如果你需要横屏和竖屏使用不同的布局文件,可能这种方式是不行的,经过我自己写代码测试,如果当前是竖屏,经过切换后它并不会使用横屏的布局文件,而是将竖屏的布局文件使用在横屏状态下,不知道是我写的不合适还是本来就这样,希望和大家讨论这个问题。                                                                                                        

禁止调用 onCreate 方法:在 Mainifest.xml 的 Activity 元素中加入 android:configChanges="orientation|keyboardHidden" 属性                                           

我写的测试程序:                                                                                                                                                                                               

view plaincopy to clipboardprint?package lzu.LandAndPortraintTest; 
 
import android.app.Activity; 
import android.content.pm.ActivityInfo; 
import android.content.res.Configuration; 
import android.os.Bundle; 
 
public class LandAndPortraintTest extends Activity { 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
        printSentence(); 
    } 
    public void printSentence(){ 
        System.out.println("printSentence"); 
    } 
    public void printPortraintSentence(){ 
        System.out.println("printSentence Portraint"); 
    } 
    public void printLandscapeSentence(){ 
        System.out.println("printSentence Landscape"); 
    } 
    public void onConfigurationChanged(Configuration newConfig) 
    {  
        super.onConfigurationChanged(newConfig);  
        if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) 
        { 
            printLandscapeSentence(); 
        } 
        else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) 
        { 
            printPortraintSentence(); 
        } 
    } 

package lzu.LandAndPortraintTest;

import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.os.Bundle;

public class LandAndPortraintTest extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        printSentence();
    }
    public void printSentence(){
     System.out.println("printSentence");
    }
    public void printPortraintSentence(){
     System.out.println("printSentence Portraint");
    }
    public void printLandscapeSentence(){
     System.out.println("printSentence Landscape");
    }
    public void onConfigurationChanged(Configuration newConfig)
    {
     super.onConfigurationChanged(newConfig);
     if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
     {
      printLandscapeSentence();
     }
     else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
     {
      printPortraintSentence();
     }
    }
} layout-land 下 main.xml 文件:view plaincopy to clipboardprint?<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    > 
<TextView   
    android:layout_width="fill_parent"  
    android:layout_height="wrap_content"  
    android:text="@string/hello" 
    /> 
</LinearLayout> 
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello"
    />
</LinearLayout>layout-port 下 main.xml 文件:view plaincopy to clipboardprint?<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    > 
<TextView   
    android:layout_width="fill_parent"  
    android:layout_height="wrap_content"  
    android:text="@string/app_name" 
    /> 
</LinearLayout> 
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/app_name"
    />
</LinearLayout>
values 下 strings.xml 文件:view plaincopy to clipboardprint?<?xml version="1.0" encoding="utf-8"?> 
<resources> 
    <string name="hello">Hello World, LandAndPortraintTest!</string> 
    <string name="app_name">LandAndPortraintTest</string> 
</resources> 
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World, LandAndPortraintTest!</string>
    <string name="app_name">LandAndPortraintTest</string>
</resources>

Android 如何只禁止某一个Layout在横竖屏切换的时候重新加载

Android 如何只禁止某一个Layout在横竖屏切换的时候重新加载

Android中有办法让一个Activity只加载port/land布局,如:

android:screenOrientation="portrait"

android:screenOrientation="landscape"

我现在想,只固定某一个Layout为竖直方向,如何能做到呢?

今天的关于Android 实现视频字幕Subtitle和横竖屏切换示例android视频播放横竖屏切换的分享已经结束,谢谢您的关注,如果想了解更多关于Android Activity 横竖屏切换的生命周期、Android Activity横竖屏切换生命周期详解、android 中禁止横竖屏切换、Android 如何只禁止某一个Layout在横竖屏切换的时候重新加载的相关知识,请在本站进行查询。

本文标签: