欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android 實(shí)現(xiàn)視頻字幕Subtitle和橫豎屏切換示例

 更新時(shí)間:2018年01月24日 15:14:24   作者:高-富-帥  
下面小編就為大家分享一篇Android 實(shí)現(xiàn)視頻字幕Subtitle和橫豎屏切換示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧

系統(tǒng)自帶的VideoView有些視頻格式不支持,那么我們可以用第三方實(shí)現(xiàn)的VideoView替代系統(tǒng)的來(lái)播放視頻,比較流行的有ijkplayer、vitamio

最近有個(gè)需求就是需要給視頻添加字幕,其實(shí)也挺簡(jiǎn)單的。字幕比較常用的格式是srt,實(shí)際它就是文本,把它解析出來(lái),然后根據(jù)時(shí)間再展示就OK。還有就是實(shí)現(xiàn)了即使旋轉(zhuǎn)按鈕關(guān)閉,根據(jù)方向感應(yīng)器也能做到橫豎屏切換。

本文用的是系統(tǒng)VideoView,然后播放sd卡中的視頻來(lái)作為演示(源碼中帶有f2.mp4和f2.srt,運(yùn)行時(shí)拷貝到sd卡就行)。下面簡(jiǎn)單介紹一下源碼:

MainActivity包括顯示字幕和如何實(shí)現(xiàn)橫豎屏如何切換:

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;// 用于記錄是否關(guān)閉屏幕旋轉(zhuǎn),0為關(guān)閉1為開(kāi)啟
	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執(zhí)行一次showSRT(),根據(jù)時(shí)間匹配顯示哪句字幕
					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);//項(xiàng)目中顯示字幕的控件
	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代表開(kāi)啟自動(dòng)旋轉(zhuǎn)true,0代表未開(kāi)啟自動(dòng)旋轉(zhuǎn)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);
		//設(shè)置視頻控制器
// videoView.setMediaController(new MediaController(this));
		//播放完成回調(diào)
		videoView.setOnCompletionListener( new MyPlayerOnCompletionListener());
		videoView.setOnPreparedListener(new OnPreparedListener() {
			//@Override
			public void onPrepared(MediaPlayer mp) {
				totalDuration=videoView.getDuration();
				if (mTotalTime != null)
			mTotalTime.setText("/"+generateTime(totalDuration));
			}
		});
		//設(shè)置視頻路徑
		videoView.setVideoURI(uri);
		//開(kāi)始播放視頻
		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="標(biāo)清";
		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", minutes, 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();
		/**
		 * 這里點(diǎn)擊按鈕轉(zhuǎn)屏,用戶(hù)5秒內(nèi)不轉(zhuǎn)屏幕,將自動(dòng)識(shí)別當(dāng)前屏幕方向
		 */
		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() {
//		手動(dòng)旋轉(zhuǎn)屏幕,5s后會(huì)執(zhí)行感應(yīng)的方向
		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為了適應(yīng)一開(kāi)始就有空行以及其他不符格式的空行情況
  if (parseStrs.length < 3) {
   sb.delete(0, sb.length());// 清空,否則影響下一個(gè)字幕元素的解析</i>
   continue;
  }
  SRT srt = new SRT();
  // 解析開(kāi)始和結(jié)束時(shí)間
  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("開(kāi)始:" + begin_hour + ":" + begin_mintue +
   ":"
   + begin_scend + ":" + begin_milli + "=" + beginTime
   + "ms");
  System.out.println("結(jié)束:" + 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";
  }
  // 刪除最后一個(gè)"\n"
  srtBody = srtBody.substring(0, srtBody.length() - 1);
  // 設(shè)置SRT
  srt.setBeginTime(beginTime);
  srt.setEndTime(endTime);
  srt.setSrtBody(new String(srtBody.getBytes(), "UTF-8"));
  srtList.add(srt);
  sb.delete(0, sb.length());// 清空,否則影響下一個(gè)字幕元素的解析
  }
  lastEndTime=srtList.get(srtList.size()-1).getEndTime();
  br.close();
 } catch (IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 }
 //每隔500ms執(zhí)行一次()取
 }
 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());
  //顯示過(guò)的就刪掉,提高查詢(xún)效率
  srtList.remove(i);
  break;//找到后就沒(méi)必要繼續(xù)遍歷下去,節(jié)約資源
  }
 }
 }
}

運(yùn)行效果圖:

項(xiàng)目源碼,點(diǎn)擊下載......

以上這篇Android 實(shí)現(xiàn)視頻字幕Subtitle和橫豎屏切換示例就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android實(shí)現(xiàn)一個(gè)簡(jiǎn)單的單詞本

    Android實(shí)現(xiàn)一個(gè)簡(jiǎn)單的單詞本

    大家好,本篇文章主要講的是Android實(shí)現(xiàn)一個(gè)簡(jiǎn)單的單詞本,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話(huà)記得收藏一下
    2022-01-01
  • Android?WebView軟鍵盤(pán)遮擋輸入框方案詳解

    Android?WebView軟鍵盤(pán)遮擋輸入框方案詳解

    這篇文章主要介紹了Android?WebView軟鍵盤(pán)遮擋輸入框方案詳解,本文提供了一種新的解決?WebView?輸入框被軟鍵盤(pán)遮擋的思路,不過(guò)這種思路也有它的局限性,目前來(lái)看僅適用于全屏的?WebView?中,需要的朋友可以參考下
    2022-06-06
  • 解決Android屏幕四周閃現(xiàn)紅框的問(wèn)題

    解決Android屏幕四周閃現(xiàn)紅框的問(wèn)題

    這篇文章主要介紹了解決Android屏幕四周閃現(xiàn)紅框的問(wèn)題,需要的朋友可以參考下
    2017-06-06
  • android仿Adapter實(shí)現(xiàn)自定義PagerAdapter方法示例

    android仿Adapter實(shí)現(xiàn)自定義PagerAdapter方法示例

    這篇文章主要給大家介紹了關(guān)于android仿Adapter實(shí)現(xiàn)自定義PagerAdapter的相關(guān)資料,文中詳細(xì)介紹了關(guān)于PagerAdapter的用法,對(duì)大家的理解和學(xué)習(xí)具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-11-11
  • Android DrawableTextView圖片文字居中顯示實(shí)例

    Android DrawableTextView圖片文字居中顯示實(shí)例

    在我們開(kāi)發(fā)中,TextView設(shè)置Android:drawableLeft一定使用的非常多,但Drawable和Text同時(shí)居中顯示可能不好控制,小編想到通過(guò)自定義TextView實(shí)現(xiàn),具體詳情大家參考下本文
    2017-03-03
  • Android中查看USB連接的外接設(shè)備信息的代碼實(shí)例

    Android中查看USB連接的外接設(shè)備信息的代碼實(shí)例

    這篇文章主要介紹了Android中查看USB連接的外接設(shè)備信息的代碼實(shí)例,需要的朋友可以參考下
    2014-04-04
  • android實(shí)現(xiàn)計(jì)步功能初探

    android實(shí)現(xiàn)計(jì)步功能初探

    這篇文章主要介紹了android實(shí)現(xiàn)計(jì)步功能初探,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • Android SearchView搜索框組件的使用方法

    Android SearchView搜索框組件的使用方法

    這篇文章主要為大家詳細(xì)介紹了Android SearchView搜索框組件的使用方法,即時(shí)搜索提示功能的實(shí)現(xiàn),感興趣的小伙伴們可以參考一下
    2016-05-05
  • Android實(shí)現(xiàn)輪播圖片效果

    Android實(shí)現(xiàn)輪播圖片效果

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)輪播圖片效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • Android小程序?qū)崿F(xiàn)音樂(lè)播放列表

    Android小程序?qū)崿F(xiàn)音樂(lè)播放列表

    這篇文章主要為大家詳細(xì)介紹了Android小程序?qū)崿F(xiàn)音樂(lè)播放列表,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05

最新評(píng)論