編輯:關於Android編程
實現一個播放器裡的全屏播放功能
視頻播放器的核心是:VideoView
使用AndroidStudio設置Activity的全橫屏會出現閃退
解決方法:
把運行類的繼承改成Activity就可以了
有兩種實現全屏的方法
第一種是配置xml第二種是運行類中編寫代碼實現
第一種實現方式:
在xml配置一下當前Activity為橫屏不可切換豎屏
1、在清單文件AndroidManifest.xml的Activity標簽中加入android:screenOrientation="landscape"
2、在清單文件AndroidManifest.xml的application標簽中加入android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
這裡的視頻文件是網上的鏈接 所以要記得加入INTERNET權限
第二種:
在運行類中加入代碼實現全屏
requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
現在要實現主頁的Activity跳轉到全屏的Activity播放的話不能在全屏播放的類中加上
requestWindowFeature(Window.FEATURE_NO_TITLE);
會使主頁的Activity沒有標題 如果就像讓它無標題那就設置 這裡的類如果不是繼承Activity的話 點擊播放就會閃退
想實現的效果如下圖:
主要效果是為了實現全屏的功能 所以不完善其他功能 視頻文件也是指定好的網上文件 沒有什麼緩沖等等
主頁面很簡單就是一個按鈕 點擊按鈕後打開全屏播放視頻
xml布局如下
package com.example.szh.day10; import android.content.Intent; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; public class Index extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_index); } public void player3(View view){ Intent intent = new Intent(this,VideoViewActivity.class); startActivity(intent); } }
第二個界面全屏功能
已具備的功能:
1、在全屏狀態下可以左右滑動定位到影片的進度位置 這裡設置的為1秒
2、seekBar控件可以滑動定位到指定視頻位置播放
3、暫停
4、播放
5、停止
6、單擊視頻播放器的時候回出現控制器 控制器在2秒後隱藏 控制器的顯示和隱藏調用了簡單的動畫效果
代碼如下
package com.example.szh.day10; import android.app.Activity; import android.media.MediaPlayer; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.view.animation.Animation; import android.view.animation.TranslateAnimation; import android.widget.LinearLayout; import android.widget.SeekBar; import android.widget.VideoView; import java.util.Timer; import java.util.TimerTask; public class VideoViewActivity extends Activity { private VideoView videoView; private SeekBar seekBar; private Timer timer;//javase中的計時器 private TimerTask timerTask;//任務棧 private LinearLayout control;//視頻的控制器對應的布局ID private int pause = 0;//暫停用來獲取暫停時影片的進度 private int startX;//落下的X坐標 int seek =0;//左右滑動時更新seek的值修改到SeekBar中 int up = 0;//計算用戶落下的坐標和離開時的坐標可供下面判斷左右滑動 int change = 0;//用戶滑動的坐標變化 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_video_view); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); control = (LinearLayout) findViewById(R.id.control); seekBar = (SeekBar) findViewById(R.id.sb); videoView = (VideoView) findViewById(R.id.videoView); //播放地址 videoView.setVideoPath("http://hc.yinyuetai.com/uploads/videos/common/5BAA0126EA2C38ACF34DA" + "07ECF52DCBB.flv?sc\\u003d63348fe3ecf23d32\\u0026br\\u003d549\\u0026vid\\u003d32456" + "\\u0026aid\\u003d311\\u0026area\\u003dHT\\u0026vst\\u003d2"); //開始播放 videoView.start(); //setOnPreparedListener數據准備事件,准備好了才給SeekBar賦值 /* * int duration = videoView.getDuration();//獲取視頻的時長 * seekBar.setMax(duration);//設置seekBar的最大值為視頻的時長 * 這裡的賦值不能寫在監聽事件以外 * 之前我寫在了timerTask裡面導致播放斷斷續續 * 寫在了videoView.start();之後又獲取不到視頻的長度 * 想了許久後發現之前寫的MP3播放是需要准備監聽事件去解決主線程阻塞的情況, * 於是就想 是不是MP4也需要讓它先判斷是否准備完成、於是上網浏覽了下 * setOnPreparedListener的用法後才知道 視頻也是需要這個事件才可以 * * */ videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { int duration = videoView.getDuration();//獲取視頻的時長 seekBar.setMax(duration);//設置seekBar的最大值為視頻的時長 } }); /* * 新建javase中的計時器和任務棧 * 任務棧中要實現SeekBar的進度的實時更新 * * */ timer = new Timer(); timerTask = new TimerTask() { @Override public void run() { //獲取當前視頻的時間 int progess = videoView.getCurrentPosition(); //設置SeekBar的進度 seekBar.setProgress(progess); } }; //每1秒執行一次 立刻執行 timer.schedule(timerTask, 0, 1000); //SeekBar的滑動事件 seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { //值的改變 不實現這個功能 @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } //開始觸摸SeekBar監聽事件不實現這個功能 @Override public void onStartTrackingTouch(SeekBar seekBar) { } //用戶滑動後離開SeekBar調用的事件 @Override public void onStopTrackingTouch(SeekBar seekBar) { //獲取離開時的值 int progress = seekBar.getProgress(); //設置視頻從該值開始播放 videoView.seekTo(progress); } }); } /* * 開始播放按鈕 * */ public void start(View view){ //先判斷是否暫停 if(pause!=0){ videoView.start(); videoView.seekTo(pause); pause=0; }else if(!videoView.isPlaying()&&pause==0){ videoView.start(); } } /* * 暫停 並把當前視頻的時間賦值給pause變量 * */ public void pause(View view){ videoView.pause(); pause = videoView.getCurrentPosition(); } /* * 停止 設置視頻到0秒播放並且暫停 * */ public void stop(View view){ videoView.seekTo(0); videoView.pause(); } //Activity被銷毀後要釋放掉資源 @Override protected void onDestroy() { timer.cancel(); timerTask.cancel(); timer = null; timerTask = null; super.onDestroy(); } //為Activity設置觸摸事件 @Override public boolean onTouchEvent(MotionEvent event) { //event.getAction()獲取事件的狀態 switch (event.getAction()){ //當用戶單擊屏幕的時候控制被調出 case MotionEvent.ACTION_DOWN://按下 //獲取用戶按下時的X坐標 startX = (int) event.getX(); //把判斷左右滑動的值歸0 up=0; //判斷控制器是否隱藏 一開始布局的配置是先讓控制隱藏 if(control.getVisibility()== View.VISIBLE){//如果控制器可見就設置為不可見 control.setVisibility(View.INVISIBLE);//隱藏 //移動的動畫 這裡不做詳細解析 TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_SELF ,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0F,Animation.RELATIVE_TO_SELF,1.0F); //動畫的時間 ta.setDuration(200); //動畫開始 control.startAnimation(ta); }else if(control.getVisibility()== View.INVISIBLE){//如果控制器不可見就設置可見 control.setVisibility(View.VISIBLE);//顯示 //移動的動畫 這裡不做詳細解析 TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_SELF ,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,1.0f,Animation.RELATIVE_TO_SELF,0f); //動畫的時間 ta.setDuration(200); //動畫開始 control.startAnimation(ta); //顯示後用戶沒有再進行頁面的任何操作時 2秒後自動隱藏控制器 new Thread(){ @Override public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } runOnUiThread(new Runnable() { @Override public void run() { control.setVisibility(View.INVISIBLE);//隱藏 TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_SELF ,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0F,Animation.RELATIVE_TO_SELF,1.0F); ta.setDuration(200); control.startAnimation(ta); } }); } }.start(); } break; case MotionEvent.ACTION_MOVE://移動 change = (int) event.getX();//獲取到移動的X軸的值 up = startX - change;//實時賦值給up變量 break; case MotionEvent.ACTION_UP://離開 up = 0; break; } //使用startX - change得到的值 結果為負 就是向右移動 反之向左移動 if(up<0){ //獲取當前視頻的播放進度 int currentPosition = videoView.getCurrentPosition(); //當前視頻的播放進度再加1秒 seek = currentPosition + 1000; //這個值不能大於視頻的長度 if (seek <= videoView.getDuration()) { videoView.seekTo(seek); } }else if(up>0){ //獲取當前視頻的播放進度 int currentPosition = videoView.getCurrentPosition(); //當前視頻的播放進度減1秒 seek = currentPosition - 1000; //這個值不能小於0 if (seek >= 0) { videoView.seekTo(seek); } } return super.onTouchEvent(event); } }主清單文件如下
功能並不完善 以後有時間的話回頭繼續寫 目標把它做成一個功能完善的視頻播放器~~~~~~~~~~~~~~~~
上一篇大概分析了一下FM啟動流程,若不了解Fm啟動流程的,可以去打開前面的鏈接先了解FM啟動流程,接下來我們簡單分析一下FM的搜索頻率流程。 在了解源碼之前,我們先看一下
Android中的ListView是一個經常用到的控件,ListView裡面的每個子項Item可以使一個字符串,也可以是一個組合控件。本文先來說說ListView的實現:
項目中經常需要底部彈出框,這裡我整理一下其中我用的比較順手的一個方式(底部彈出一個橫向滿屏的dialog)。效果圖如下所示(只顯示關鍵部分):步驟如下所示:1.定義一個d
先給大家展示下效果圖:package com.lixu.circlemenu; import android.app.Activity; import android.o