1.1.依赖 http库,gson库,RecyclerView+CardView库,design包,Glide库,butterknife库,Adapter-Helper库(BaseQuickAdapter)
1.2.还需搭建vr开发环境.
1.2.1.导入vr开发相关的库 common, commonwidget,通用。全景图片panowidget,全景视频videowidget
1.2.2.配置应用获取最大内存,防止内存不足选成内存溢出
2.1.删除ActionBar只在主题风格下面进行NoActionBar配置即可
2.2.布局指示器TabLayout 布局ViewPager
2.3.查找出来进行初始化
2.3.1.创建适配器给ViewPager
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.itheima.vrproject97">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:name=".VrApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:largeHeap="true"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".activity.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
intent-filter>
activity>
<activity android:name=".activity.VrImagePlayActivity" />
<activity android:name=".activity.VrVideoDesActivity" />
<activity android:name=".activity.VrVideoPlayActivity" />
application>
manifest>
public class VrApp extends Application {
@Override
public void onCreate() {
super.onCreate();
//NoHttp初始化简单配置
NoHttp.initialize(this);
}
}
//步骤一 。完成构造函数
public class StateLayout extends FrameLayout {
private View mLoading = null;
private View mError = null;
private View mEmpty = null;
private View mNormal = null;
public StateLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//步骤二 将布局打气进来并且作为一个元素添加当前的容器
View view = View.inflate(context, R.layout.state_layout, null);
mLoading = view.findViewById(R.id.loading);
mError = view.findViewById(R.id.error);
mEmpty = view.findViewById(R.id.nodata);
// mNormal = view.findViewById(R.id.normal);
this.addView(view);
}
public StateLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public StateLayout(Context context) {
this(context, null, 0);
}
//三。重置让所有的控件变成gone
private void reset() {
mLoading.setVisibility(View.GONE);
mError.setVisibility(View.GONE);
mEmpty.setVisibility(View.GONE);
if (mNormal != null) {
mNormal.setVisibility(View.GONE);
}
}
//显示加载中
public void showLoading() {
reset();
mLoading.setVisibility(View.VISIBLE);
}
//显示网络出错
public void showError() {
reset();
mError.setVisibility(View.VISIBLE);
}
//显示空
public void showEmpty() {
reset();
mEmpty.setVisibility(View.VISIBLE);
}
public void addNormalView(Object normalViewLayout) {
if (normalViewLayout instanceof Integer) {
mNormal = LayoutInflater.from(getContext()).inflate((Integer) normalViewLayout, this, false);
} else {
mNormal = (View) normalViewLayout;
}
this.addView(mNormal);//只有添加到当前布局的元素才可以显示
}
//显示正常
public void showNormal() {
reset();
mNormal.setVisibility(View.VISIBLE);
}
}
布局界面 state_layout.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/loading"
style="@android:style/Widget.ProgressBar.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
<TextView
android:id="@+id/error"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:drawablePadding="10dp"
android:drawableTop="@drawable/ic_error_page"
android:gravity="center_horizontal|bottom"
android:text="加载失败,点击重试"
android:visibility="gone" />
<ImageView
android:id="@+id/nodata"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_empty_page" />
FrameLayout>
ApiUrls
地址工具类,方便以后更改地址
public class ApiUrls {
public static final String HOST="http://192.168.191.1:8080";
public static final String IMAGE_LIST=HOST+"/vr/imagelist";
public static final String VIDEO_LIST=HOST+"/vr/videolist";
}
HttpUtils
封装联网工具
public class HttpUtils {
private static RequestQueue queue;
public static void get(String url, OnResponseListener callBack) {
//创建请求xml/json
StringRequest request = (StringRequest) NoHttp.createStringRequest(url, RequestMethod.GET);//1.连接地址 2.请求方法
//设置缓存模式
request.setCacheMode(CacheMode.REQUEST_NETWORK_FAILED_READ_CACHE);
if (queue == null) {
queue = NoHttp.newRequestQueue();
}
// 1.提供多个空的方法 编写业务逻辑
//2.每个方法都对应一个情况 成功 失败
queue.add(0, request, callBack);//1.请求what 2.请求 3.回调对象:处理结果的对象。
}
}
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.itheima.vrproject97.activity.MainActivity">
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:id="@+id/tabs">
android.support.design.widget.TabLayout>
<android.support.v4.view.ViewPager
android:layout_marginTop="50dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/viewpager">
android.support.v4.view.ViewPager>
FrameLayout>
MainActivity的代码
public class MainActivity extends AppCompatActivity {
@InjectView(R.id.tabs)
TabLayout tabs;
@InjectView(R.id.viewpager)
ViewPager viewpager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
MainFragmentAdapter adapter = new MainFragmentAdapter(getSupportFragmentManager());
viewpager.setAdapter(adapter);
//2.3.2设置tabLayout外观
//字体
tabs.setTabTextColors(Color.parseColor("#707070"),Color.parseColor("#FF9648"));
//滑块颜色
tabs.setSelectedTabIndicatorColor(Color.parseColor("#FF9648"));
//滑块高度
tabs.setSelectedTabIndicatorHeight(4);
//2.3.3.把ViewPager设置给TabLayout
tabs.setupWithViewPager(viewpager);
}
private class MainFragmentAdapter extends FragmentPagerAdapter {
private String[] mTitles = new String[]{"全景图", "全景视频"};
private Fragment[] mPages = new Fragment[]{new VrPanoFragment(), new VrVideoFragment()};
public MainFragmentAdapter(FragmentManager fm) {
super(fm);
}
//返回指示需要的标题
@Override
public CharSequence getPageTitle(int position) {
return mTitles[position];
}
//返回页面内容
@Override
public Fragment getItem(int position) {
return mPages[position];
}
//返回页面数量
@Override
public int getCount() {
return mTitles.length;
}
}
}
VrPanoFragment
public class VrPanoFragment extends BaseFragment {
}
BaseFragment
public class BaseFragment extends Fragment {
private StateLayout stateLayout;
protected RecyclerView recyclerView;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//步骤一。创建页面基本组成
//1.1.创建StateLayout实例
stateLayout = new StateLayout(container.getContext());
//1.2.创建列表RecyclerView
recyclerView = new RecyclerView(container.getContext());
//1.3.显示方式
recyclerView.setLayoutManager(getLayout(container));
stateLayout.addNormalView(recyclerView);
//1.4.显示loading
stateLayout.showLoading();
//步骤二。获取服务端数据进行显示
//2.1.阅读接口文档,测试接口正常 http://192.168.79.34:8080/vr/imagelist
//2.2.发送请求(nohttp框架初始化)
getPageData();
return stateLayout;
}
public void getPageData() {
//2.3.在Callback对应条件的空方法里编写业务逻辑
final OnResponseListener callBack = new OnResponseListener() {
@Override
public void onStart(int what) {
stateLayout.showLoading();
}
@Override
public void onFinish(int what) {
stateLayout.showNormal();
}
@Override
public void onFailed(int what, Response response) {
stateLayout.showError();
}
@Override
public void onSucceed(int what, Response response) {
//2.4.获取返回的json数据
String json=response.get();
//2.5.如果没问题再使用gsonFormat来解析
Object data = processJson(json);
//2.6展示数据
showData(data);
}
};
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
HttpUtils.get(loadUrl(), callBack);
}
}, 1000);
}
@NonNull
protected RecyclerView.LayoutManager getLayout(@Nullable ViewGroup container) {
return new LinearLayoutManager(container.getContext());
}
@NonNull
protected String loadUrl() {
return ApiUrls.IMAGE_LIST;
}
protected Object processJson(String json) {
return new Gson().fromJson(json,ImageData.class);
}
protected void showData(Object data) {
ImageData imageData= (ImageData) data;
System.out.println(data);
//步骤三。展示解析成功的数据
VrPanoAdaper adapter=new VrPanoAdaper(R.layout.item_image_card,imageData.list);
recyclerView.setAdapter(adapter);
}
}
ImageData 的bean类
public class ImageData {
public List list;
public static class ImageItem implements Serializable{
/**
* mp3 : http://media.qicdn.detu.com/@/13363707-8857-C248-3CE1-64F2F24291636/source/145049/o_1arbdk2apj37df16up16um196j7.mp3
* title : 滕王阁
* url : http://media.qicdn.detu.com/pano177051472357986990056825/thumb/500_500/panofile.jpg
*/
public String mp3;
public String title;
public String url;
}
}
界面布局 item_image_card.xml
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="6dp"
card:cardCornerRadius="6dp"
card:cardElevation="10dp">
<include layout="@layout/item_image" />
界面布局 item_image.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/image"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="150dp" />
<TextView
android:layout_marginTop="6dp"
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="--"
android:textColor="#000000"
android:textSize="22sp" />
LinearLayout>
创建适配器 VrPanoAdaper
继承快速的适配器,在适配器中设置内容,设置点击事件
//3.1.创建适配器类
public class VrPanoAdaper extends BaseQuickAdapter<ImageData.ImageItem> {
//3.2.指定布局给适配器
public VrPanoAdaper(int layoutResId, List data) {
super(layoutResId, data);
}
//3.3.赋值
@Override
protected void convert(BaseViewHolder helper, final ImageData.ImageItem item) {
//3.3.1赋值
helper.setText(R.id.text, item.title);
//3.3.2.加载图片
Glide.with(mContext).load(item.url).into((ImageView) helper.getView(R.id.image));
helper.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(v.getContext(), VrImagePlayActivity.class);
intent.putExtra("item",item);//要求javaBean实现序列化 implements Serializable
v.getContext().startActivity(intent);//打开
}
});
}
}
设置条目点击事件转到展示页面—VrImagePlayActivity
public class VrImagePlayActivity extends AppCompatActivity {
private VrPanoramaView vrPanoramaView;
private ImageTask imageTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent=getIntent();
ImageData.ImageItem item= (ImageData.ImageItem) intent.getSerializableExtra("item");
//步骤一。搭建VR图片开发的环境
//1.1.导入从github搜索下载的google vr sdk 里面的引用库 common,commonwidget,panowidget(全景图片控件库)
//1.2.当前这三个库里面缺少序列相关的api,容易引用类找不到,未定义异常
//1.3.依赖三个库
//1.4.准备全景图片用来测试代码 放在assets目录下面,例assets/a.jpg
//1.5.对当前应用进行内存设置,希望应用可使用最大内存 避免OOM
//步骤二。加载全景图片到内存中成为Bitmap(bitmap是图片在内存中的表示对象),展示在全景图片控件
//2.1.布局全景图片控件
//2.2.查找控件
vrPanoramaView = new VrPanoramaView(this);
setContentView(vrPanoramaView);
//2.3.因为图片比较大,希望在异步线程里面加载,防止占用主线程
imageTask = new ImageTask();
imageTask.execute(item.url);
}
private class ImageTask extends AsyncTask<String,Void,Bitmap>
{
//2.4.读取资产目录下面的a.jpg图片
@Override
protected Bitmap doInBackground(String... params) {
try {
//2.4.1.获取网络流
URL url=new URL(params[0]);
HttpURLConnection connection= (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(10000);
InputStream inputStream =connection.getInputStream();
//2.4.2.使用BitmapFactory可以将inputStream,file,byte[]-->Bitmap
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
//2.5.在主线程展示位图
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if(bitmap!=null)
{
//加载bitmap到vr图片控件 参1.Bitmap
VrPanoramaView.Options options=new VrPanoramaView.Options() ;
//TYPE_STEREO_OVER_UNDER :立体图片:上半画面显示在左眼,下半画面显示在右眼
//TYPE_MONO :普通图片
options.inputType= VrPanoramaView.Options.TYPE_MONO;
//3.1.监听加载过程
VrPanoramaEventListener listener=new VrPanoramaEventListener(){
//3.1.1.加载bitmap异常
@Override
public void onLoadError(String errorMessage) {
super.onLoadError(errorMessage);
Toast.makeText(VrImagePlayActivity.this, errorMessage, Toast.LENGTH_SHORT).show();
}
//3.1.2.加载bitmap成功
@Override
public void onLoadSuccess() {
super.onLoadSuccess();
Toast.makeText(VrImagePlayActivity.this, "进入VR图片显示...", Toast.LENGTH_SHORT).show();
}
};
vrPanoramaView.setEventListener(listener);
vrPanoramaView.loadImageFromBitmap(bitmap,options);
}
}
}
//步骤三。处理全景控件展示细节
//3.2.页面停到后台,暂停画面显示
@Override
protected void onPause() {
super.onPause();
if (vrPanoramaView != null) {
vrPanoramaView.pauseRendering();
}
}
//3.3.页面回到屏幕,再继续显示
@Override
protected void onResume() {
super.onResume();
if (vrPanoramaView != null) {
vrPanoramaView.resumeRendering();
}
//3.5.按钮控制
//3.5.1隐藏info按钮
vrPanoramaView.setInfoButtonEnabled(false);
//3.5.2隐藏全屏按钮
vrPanoramaView.setFullscreenButtonEnabled(false);
//3.5.3.展示全屏
//FULLSCREEN_MONO 全屏模式
//FULLSCREEN_STEREO CardBoard 纸盒
vrPanoramaView.setDisplayMode(VrWidgetView.DisplayMode.FULLSCREEN_MONO);
}
//3.4.页面关闭,销毁图片
@Override
protected void onDestroy() {
super.onDestroy();
if (vrPanoramaView != null) {
vrPanoramaView.shutdown();
}
if (imageTask != null && !imageTask.isCancelled()) {
//防止页面退出AsyncTask引用的异常
imageTask.cancel(true);
imageTask = null;
}
}
}
到这,图片的fragment的页面就已经设置好了
VrVideoFragment
public class VrVideoFragment extends BaseFragment {
//1.指定新的请求路径
@Override
protected String loadUrl() {
return ApiUrls.VIDEO_LIST;
}
//2.重写排列方式
@NonNull
@Override
protected RecyclerView.LayoutManager getLayout(@Nullable ViewGroup container) {
GridLayoutManager gridLayoutManager = new GridLayoutManager(container.getContext(), 2);
return gridLayoutManager;
}
//3.处理服务端返回数据
@Override
protected Object processJson(String json) {
return new Gson().fromJson(json, VideoData.class);
}
//4.展示视频数据
@Override
protected void showData(Object data) {
VideoData videoData = (VideoData) data;
VrVideoAdapter vrVideoAdapter=new VrVideoAdapter(R.layout.item_video_card,videoData.content);
recyclerView.setAdapter(vrVideoAdapter);
}
}
VideoData 的bean类
public class VideoData {
public String api;
public int qtime;
public int status;
public String message;
public String accessKey;
public String voipId;
public String voipPwd;
public List content;
public static class VideoItem implements Serializable{
public String vtype;
public String id;
public String key;
public String play;
public String title;
public String text;
public String img;
public String url;
public String isbn;
public String t0;
public String t1;
public String t2;
public String userName;
public String userNick;
public String userPhoto;
public String vclass;
public int width;
public int height;
public double score0;
public long date;
public String _id;
public String userId;
public int cnt;
public String type;
public String videoChannelName;
public String videoChannelId;
public String textSimple;
public String dateCnSimple;
public List tags;
}
}
item_video_card.xml
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="6dp"
card:cardCornerRadius="6dp"
card:cardElevation="10dp">
<include layout="@layout/item_video" />
android.support.v7.widget.CardView>
item_video.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="150dp"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/text"
android:maxLines="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="--"
android:textColor="#000000"
android:textSize="16sp" />
<RelativeLayout
android:layout_marginTop="4dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="电影"
android:maxLines="1"
android:layout_centerVertical="true"
android:textColor="#000000"
android:textSize="16sp" />
<TextView
android:id="@+id/date"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:maxLines="1"
android:layout_height="wrap_content"
android:text="2017/10/1"
android:textColor="#000000"
android:textSize="16sp" />
RelativeLayout>
LinearLayout>
VrVideoAdapter
//1.继承 BaseQuickAdapter指定类型
public class VrVideoAdapter extends BaseQuickAdapter<VideoData.VideoItem> {
//2.设置布局与集合
public VrVideoAdapter(int layoutResId, List data) {
super(layoutResId, data);
}
//3.绑定数据
@Override
protected void convert(BaseViewHolder helper, final VideoData.VideoItem item) {
//3.1.绑定文字
SimpleDateFormat formate=new SimpleDateFormat("yyyy/MM/dd");
helper.setText(R.id.text,item.title)//
.setText(R.id.type,item.type)//
.setText(R.id.date,formate.format(new Date(item.date)));//
//3.2.加载图片
Glide.with(mContext).load(item.img).into((ImageView)helper.getView(R.id.image));
//添加点击事件
helper.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(v.getContext(),VrVideoDesActivity.class);
intent.putExtra("item",item);
v.getContext().startActivity(intent);
}
});
}
}
public class VrVideoDesActivity extends AppCompatActivity {
@InjectView(R.id.title_text)
TextView titleText;
@InjectView(R.id.control_bar)
LinearLayout controlBar;
@InjectView(R.id.detail_img_view)
ImageView detailImgView;
@InjectView(R.id.video_type)
TextView videoType;
@InjectView(R.id.play_link)
ImageButton playLink;
@InjectView(R.id.detail_text)
TextView detailText;
@InjectView(R.id.video_detail)
FrameLayout videoDetail;
private VideoData.VideoItem item;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_detail);
ButterKnife.inject(this);
Intent intent = getIntent();
final VideoData.VideoItem item = (VideoData.VideoItem) intent.getSerializableExtra("item");
System.out.println(item);
//设置标题
titleText.setText(item.title);
//详情
detailText.setText(item.textSimple);
//图片
Glide.with(this).load(item.img).into(detailImgView);
playLink.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(v.getContext(),VrVideoPlayActivity.class);
intent.putExtra("play",item.play);
v.getContext().startActivity(intent);
}
});
}
}
activity_video_detail .xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/video_detail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF" >
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/control_bar"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:padding="2dip" >
<TextView
android:id="@+id/title_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="8dip"
android:text=""
android:textSize="16sp" />
LinearLayout>
<RelativeLayout
android:layout_margin="4dp"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@color/gray_lighter"
android:orientation="horizontal" >
<ImageView
android:id="@+id/detail_img_view"
android:background="@color/black"
android:layout_width="match_parent"
android:scaleType="centerCrop"
android:clickable="true"
android:layout_height="200dp"
android:src="@mipmap/pictures_no"/>
<TextView
android:id="@+id/video_type"
android:padding="8dp"
android:textStyle="bold"
android:background="@color/semitransparent_light"
android:text="视频"
android:textColor="#FFFFFF"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageButton
android:id="@+id/play_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="#22222222"
android:contentDescription="播放语音"
android:gravity="center"
android:src="@drawable/mediacontroller_play_button" />
RelativeLayout>
<TextView
android:id="@+id/detail_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="8dip"
android:textColor="#AEAEAE"
android:textSize="16sp" />
LinearLayout>
ScrollView>
FrameLayout>
activity_vr_videoplay.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main"
android:layout_width="match_parent" android:layout_height="match_parent">
<com.google.vr.sdk.widgets.video.VrVideoView
android:layout_width="match_parent"
android:id="@+id/vr_video_view"
android:layout_height="match_parent">
com.google.vr.sdk.widgets.video.VrVideoView>
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/seekbar" />
<TextView
android:background="#AEAEAE"
android:textColor="#FFFFFF"
android:text="00/100s"
android:layout_width="wrap_content"
android:gravity="center"
android:layout_height="wrap_content"
android:id="@+id/time" />
LinearLayout>
<ProgressBar
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:id="@+id/loading"
android:layout_height="wrap_content" />
RelativeLayout>
VrVideoPlayActivity
播放页面有加载页面和进度条
public class VrVideoPlayActivity extends AppCompatActivity {
private VrVideoView vrVideoView;
private VideoTask videoTask;
private ProgressBar progressBar;
private TextView timeView;
private SeekBar seekBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vr_videoplay);
//步骤一。搭建全景视频的开发环境
//1.1.导入github搜索google vr sdk 的开发库 common,commonwidget,videowidget
//1.2.依赖 当前三个库缺少的api
//1.3.准备全景视频来测试程序 ,放到assets下面 例 assets/b.mp4
//1.4. 设置应用的内存选项,在内存不足时可以使用最大内存.
//步骤二。在线程加载全景视频,显示在全景视频控件上
//2.1.布局控件并查找
vrVideoView = (VrVideoView) findViewById(R.id.vr_video_view);
//2.2 创建子线程加载资源
videoTask = new VideoTask();
//2.3.传入文件名
String play=getIntent().getStringExtra("play");
videoTask.execute(play);
seekBar = (SeekBar) findViewById(R.id.seekbar);
timeView = (TextView) findViewById(R.id.time);
progressBar = (ProgressBar) findViewById(R.id.loading);
//步骤五。界面设置
//5.1.设置隐藏info
vrVideoView.setInfoButtonEnabled(false);
//5.2.设置隐藏全屏
vrVideoView.setFullscreenButtonEnabled(false);
//5.3.显示全屏
//FULLSCREEN_MONO全屏模式
//FULLSCREEN_STEREO双眼模式
vrVideoView.setDisplayMode(VrWidgetView.DisplayMode.EMBEDDED);
}
private class VideoTask extends AsyncTask {
@Override
protected Void doInBackground(String... params) {
//2.4.从资产目录加载全景视频(类似ProgressBar因为这种控件可以自己处理线程)
VrVideoView.Options options = new VrVideoView.Options();//设置参数
//立体视频:上半画面显示在左眼,下半画面显示在右眼
//普通视频:
options.inputType = VrVideoView.Options.TYPE_MONO;
//FORMAT_DEFAULT:资源 sd assets
//FORMAT_HLS :流媒体 直播
options.inputFormat = VrVideoView.Options.FORMAT_DEFAULT;
//步骤四:监听加载过程 播放过程
VrVideoEventListener listener = new VrVideoEventListener() {
//4.1.加载成功 处理加载成的显示
@Override
public void onLoadSuccess() {
super.onLoadSuccess();
progressBar.setVisibility(View.GONE);
}
//4.2.加载失败
@Override
public void onLoadError(String errorMessage) {
super.onLoadError(errorMessage);
progressBar.setVisibility(View.GONE);
Toast.makeText(VrVideoPlayActivity.this, errorMessage, Toast.LENGTH_SHORT).show();
}
//4.3.播放中 onNewFrame执行一次,代表视频播了一个画面
@Override
public void onNewFrame() {
super.onNewFrame();
//更新seekbar
seekBar.setMax((int) vrVideoView.getDuration());
seekBar.setProgress((int) vrVideoView.getCurrentPosition());
//更新时间 23.323232323
String curr = String.format("%.2f", vrVideoView.getCurrentPosition() / 1000f);
String total = String.format("%.2f", vrVideoView.getDuration() / 1000f);
timeView.setText(curr + "/" + total + "s");
}
//4.4.播放完成
@Override
public void onCompletion() {
super.onCompletion();
//设置播放位置
vrVideoView.seekTo(0);
//暂停播放
vrVideoView.pauseVideo();
isPasuse = true;
Toast.makeText(VrVideoPlayActivity.this, "播放完成,是否重播", Toast.LENGTH_SHORT).show();
}
private boolean isPasuse = false;
//4.5.操作:点击继续播放
@Override
public void onClick() {
super.onClick();
if (isPasuse) {
vrVideoView.playVideo();
isPasuse = false;
} else {
vrVideoView.pauseVideo();
isPasuse = true;
}
}
};
try {
vrVideoView.setEventListener(listener);
//加载网络视图 1.参数url 2.options
vrVideoView.loadVideo(Uri.parse(params[0]),options);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
//步骤三。根据用户的操作来调整显示(性能优化,防止黑屏)
//3.1.页面 退到后台 暂停显示
@Override
protected void onPause() {
super.onPause();
if (vrVideoView != null) {
vrVideoView.pauseRendering();
}
}
//3.2.页面 回到屏幕 打开显示
@Override
protected void onResume() {
super.onResume();
if (vrVideoView != null) {
vrVideoView.resumeRendering();
}
}
//3.3.页面 退出页面 销毁
@Override
protected void onDestroy() {
super.onDestroy();
if (vrVideoView != null) {
vrVideoView.shutdown();
}
if (videoTask != null && !videoTask.isCancelled()) {
videoTask.cancel(true);
videoTask = null;
}
}
}