package com.wasu.cs.ui; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.SparseArray; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.OvershootInterpolator; import android.view.animation.TranslateAnimation; import android.widget.TextView; import android.widget.Toast; import com.facebook.drawee.view.SimpleDraweeView; import com.wasu.cs.model.CatData; import com.wasu.cs.model.DemandProgram; import com.wasu.cs.mvp.IView.INeteaseNewsView; import com.wasu.cs.mvp.presenter.NeteaseNewsPresenter; import com.wasu.cs.utils.RelativeDateUtils; import com.wasu.cs.widget.NeteaseNewsVideoLayout; import com.wasu.cs.widget.SpacesItemDecoration; import com.wasu.cs.widget.TabFocusRecycleView; import com.wasu.cs.widget.videoview.WasuPlayerView; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import cn.com.wasu.main.R; /** * Created by chenming on 2016/8/1. * * @author chenming * @Description: 网易新闻专区body部分,用来播放新闻视频 * @email chenming@wasu.com * @date 2016/8/1 */ public class FragmentNeteaseNewsBody extends Fragment implements INeteaseNewsView, NeteaseNewsVideoLayout.PlayIndexChangedListener { private static final String TAG = "FragmentNeteaseNewsBody"; //presenter private NeteaseNewsPresenter neteaseNewsPresenter; //UI private NeteaseNewsVideoLayout mNewsVideoLayout; private RecyclerView mRecyclerView; private TabFocusRecycleView mTabs; private LinearLayoutManager mLinearLayoutManager; private MyAdapter adapter; private TranslateAnimation shakeAnim; private ActivityNeteaseNews parentActivity; //数据 private Date curDate; //记录fragment创建时的时间点 private SparseArray columeLists;//所有tab下的视频资产列表 private int curPlayingTabIndex = 0; private int curPlayingListIndex = 0; private int tabcount; private DemandProgram mDemandProgram; private String assetjsonurl; private Handler mHandler; private static final int MSG_GETREC=0; private static final int MSG_GETCATDATA=1; private boolean onGetRecData=false; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View bodyview = inflater.inflate(R.layout.fragment_neteasenews_newsbody, container, false); findViewsById(bodyview); initRecyclerView(); initTabRecyclerview(); initVideoLayout(); initAnimation(); return bodyview; } //初始化videolayout private void initVideoLayout() { mNewsVideoLayout.setFocusable(true); mNewsVideoLayout.setOnPlayIndexChangedListener(this); mNewsVideoLayout.setNextFocusRightId(R.id.netease_news_list); mNewsVideoLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mNewsVideoLayout.toggleFullScreen(); } }); mNewsVideoLayout.setOnScreenChangedListener(new WasuPlayerView.OnScreenChangedListener() { @Override public void onScreenChanged(boolean isFullScreen) { if (!isFullScreen) { if (mNewsVideoLayout != null) { mNewsVideoLayout.requestFocus(); } } } }); mNewsVideoLayout.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT && event.getAction() == KeyEvent.ACTION_DOWN) { if (mRecyclerView == null) { return true; } else if (mRecyclerView != null & adapter != null) { mRecyclerView.requestFocus(); return true; } } return false; } }); } /** * 初始化晃动动画实例 */ private void initAnimation() { curDate = new Date(); shakeAnim = new TranslateAnimation(0, 0, 4, -4); shakeAnim.setInterpolator(new OvershootInterpolator()); shakeAnim.setDuration(100); shakeAnim.setRepeatCount(3); shakeAnim.setRepeatMode(Animation.REVERSE); } //初始化tab栏 private void initTabRecyclerview() { //初始化tabs mTabs.setLayoutAndDrawable(R.layout.item_netease_right_tab, getResources().getDrawable(R.drawable.tab_normal_bg), getResources().getDrawable(R.drawable.tab_focus_redbg), getResources().getDrawable(R.drawable.tab_indicator_bg)); mTabs.setOnItemFocusChangeListener(new TabFocusRecycleView.OnItemFocusChangeListener() { @Override public void onFocusChange(int position) { //右侧tab切换,新闻列表对应进行刷新 if (adapter != null) { if (position != curPlayingTabIndex) { adapter.isPlayingIndex = -1; } else { adapter.isPlayingIndex = curPlayingListIndex; } } updataNewsList(position); } }); mTabs.setLeftFocusView(mRecyclerView); } private void updataNewsList(int index){ if (adapter==null){ return; } if (columeLists.get(index) != null) { adapter.setAssetElements(columeLists.get(index).getAssets()); adapter.notifyDataSetChanged(); }else { Toast.makeText(getActivity(), "正在为您请求数据...", Toast.LENGTH_SHORT).show(); adapter.removeAllData(); neteaseNewsPresenter.getCatData(index); } } //初始化新闻列表 private void initRecyclerView() { mRecyclerView.setHasFixedSize(true); int spacingInPixels = getResources().getDimensionPixelOffset(R.dimen.d_7dp); //设置recycleview item间隔 mRecyclerView.addItemDecoration(new SpacesItemDecoration(spacingInPixels, 1)); mRecyclerView.setItemAnimator(new DefaultItemAnimator()); mLinearLayoutManager = new LinearLayoutManager(getActivity()); mRecyclerView.setLayoutManager(mLinearLayoutManager); mRecyclerView.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { int lastfocusedindex = -1; if (adapter != null) { lastfocusedindex = adapter.getFocusIndex(); } if (hasFocus && lastfocusedindex >= 0) { if (curPlayingTabIndex == mTabs.getViewPos()) {//判断当tab下有正在播放的资产时,列表滚动到正在播放的位置 mLinearLayoutManager.scrollToPosition(curPlayingListIndex); } } if (mLinearLayoutManager == null || mRecyclerView == null) { return; } if (mRecyclerView.findViewHolderForAdapterPosition( mLinearLayoutManager.findFirstCompletelyVisibleItemPosition()) != null) { mRecyclerView.findViewHolderForAdapterPosition( mLinearLayoutManager.findFirstCompletelyVisibleItemPosition()).itemView.requestFocus(); } } }); } private void findViewsById(View bodyview) { mNewsVideoLayout = (NeteaseNewsVideoLayout) bodyview.findViewById(R.id.neteasenewsvideolay); mTabs = (TabFocusRecycleView) bodyview.findViewById(R.id.netease_tabs); mRecyclerView = (RecyclerView) bodyview.findViewById(R.id.netease_news_list); } /** * 连播回调方法 * * @param index */ @Override public void onCurrentIndex(int index) { if (mRecyclerView != null) { //当联播index超出屏幕显示范围,增加判断让列表滚动到正在播放的位置,防止程序崩溃 if (index >= mLinearLayoutManager.findLastVisibleItemPosition() || index <= mLinearLayoutManager.findFirstVisibleItemPosition()) { mLinearLayoutManager.scrollToPositionWithOffset(index, 0); } adapter.showIsPlayingTag((MyAdapter.ItemViewHolder) mRecyclerView.findViewHolderForAdapterPosition(index), index); curPlayingListIndex = index; adapter.isPlayingIndex = index;//更新适配器播放位置 } } /** * 清楚索引 * * @param index */ @Override public void cleanPlayIndex(int index) { if (adapter != null) { curPlayingListIndex = -1; curPlayingTabIndex = -1; } } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); parentActivity = (ActivityNeteaseNews)getActivity(); String CAT_URL = parentActivity.getCAT_URL(); parentActivity.showLoading(); //初始化presenter neteaseNewsPresenter = new NeteaseNewsPresenter(); neteaseNewsPresenter.attachView(this); neteaseNewsPresenter.getNeteaseNewsData(CAT_URL); mHandler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case MSG_GETREC: onGetRecData = true; playRecVideo(); break; case MSG_GETCATDATA: if (!onGetRecData){ return; } if (!mNewsVideoLayout.isPlaying() && columeLists.get(0) != null) { playvideo(0, 0); } break; } super.handleMessage(msg); } }; } /** * 播放某个tab下的某部资产 * * @param tabindex * @param listindex */ private void playvideo(int tabindex, int listindex) { mNewsVideoLayout.playVideo(tabindex, listindex); adapter.showIsPlayingTag((MyAdapter.ItemViewHolder) mRecyclerView.findViewHolderForAdapterPosition(listindex), listindex); savePlayingState(tabindex, listindex); } /** * 记录播放的tab位置和该tab下列表的位置 * * @param tab * @param list */ public void savePlayingState(int tab, int list) { curPlayingTabIndex = tab;//更新正在播放的tab的index curPlayingListIndex = list;//更新正在播放的列表资产index } /** * 数据获取失败后的回调 * * @param throwable */ @Override public void ongetDataFailed(Throwable throwable) { Toast.makeText(getActivity(), "服务器开小差去了,请稍后重试", Toast.LENGTH_SHORT).show(); throwable.printStackTrace(); } @Override public void onGetRecVideoUrl(String assetjsonurl,DemandProgram demandProgram) { this.mDemandProgram = demandProgram; this.assetjsonurl= assetjsonurl; mHandler.sendEmptyMessage(0); } /*private void firstPlayLogic(){ if (mDemandProgram != null && assetjsonurl != null) { mNewsVideoLayout.playRecVideo(assetjsonurl,mDemandProgram);//play rec news video curPlayingListIndex = -1; } else if (columeLists.get(0) != null) { playvideo(0, 0); } }*/ private void playRecVideo(){ if (mDemandProgram != null && assetjsonurl != null) { mNewsVideoLayout.playRecVideo(assetjsonurl,mDemandProgram);//play rec news video curPlayingListIndex = -1; }else { mHandler.sendEmptyMessage(MSG_GETCATDATA); } } private void initAdapterData(CatData catData){ //WLog.d("cm","init adapter"); adapter = new MyAdapter(catData.getAssets()); mRecyclerView.setAdapter(adapter); adapter.notifyDataSetChanged(); mNewsVideoLayout.setParent(this); mNewsVideoLayout.addCatData(catData,0); parentActivity.hideLoading(); mHandler.sendEmptyMessage(MSG_GETCATDATA); } /** * tab栏目下的数据回调方法 * @param catData * @param index */ @Override public void onGetCatData(CatData catData, int index) { if (catData==null){ return; } columeLists.put(index,catData); mNewsVideoLayout.addCatData(catData,index); if (adapter==null) { initAdapterData(catData); }else if (index == mTabs.getViewPos()){//当数据请求成功并且tab栏位置正好和回调数据的index相同时才刷新列表 updataNewsList(index); } } @Override public void onGetTabTitle(SparseArray spname) { mTabs.setData(spname); } @Override public void onGetJsonUrls(SparseArray jsonUrls) { if (jsonUrls == null) { return; } tabcount = jsonUrls.size(); mNewsVideoLayout.setJsonUrls(jsonUrls);//给videolayout设置播放地址 columeLists = new SparseArray<>(tabcount); neteaseNewsPresenter.getCacheData();//初始化第一个tab } private void recycleMemory() { if (shakeAnim != null) { shakeAnim = null; } if (neteaseNewsPresenter != null) { neteaseNewsPresenter = null; } if (mNewsVideoLayout != null) { mNewsVideoLayout = null; } if (mRecyclerView != null) { mRecyclerView = null; } if (mTabs != null) { mTabs = null; } if (mLinearLayoutManager != null) { mLinearLayoutManager = null; } if (adapter != null) { adapter = null; } if (parentActivity != null) { parentActivity = null; } if (curDate != null) { curDate = null; } if (columeLists != null) { columeLists = null; } } @Override public void onStop() { super.onStop(); if (mNewsVideoLayout!=null){ mNewsVideoLayout.stopPlaying(); mNewsVideoLayout.removePlayIndexChangedListener(); } recycleMemory(); } class MyAdapter extends RecyclerView.Adapter { List assetElements; private int focusIndex = -1;//记录焦点位置 private int isPlayingIndex = -1;//记录正在播放的位置 private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private Date date = new Date(); public int getFocusIndex() { return focusIndex <= 0 ? 0 : focusIndex; } public void setFocusIndex(int focusIndex) { this.focusIndex = focusIndex; } public void setAssetElements(List assetElements) { this.assetElements = assetElements; } public void removeAllData(){ assetElements =null; notifyDataSetChanged(); } public MyAdapter(List assetElements) { if (null == assetElements) { throw new IllegalArgumentException("netease news adapter data must not be null"); } this.assetElements = assetElements; } @Override public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(getActivity()).inflate(R.layout.item_netease_news, null); ItemViewHolder viewHolder = new ItemViewHolder(view); return viewHolder; } @Override public void onBindViewHolder(final ItemViewHolder holder, final int position) { final CatData.AssetElement assetElement = assetElements.get(position); holder.title.setText(assetElement.getTitle()); holder.timetag.setText(calDateTime(assetElement.getTime())); // ImageFetcherModule.getInstance().attachImage(assetElement.getPicUrl(), holder.simpleDraweeView); holder.simpleDraweeView.setImageURI(assetElement.getPicUrl()); if (isPlayingIndex == holder.getLayoutPosition()) { holder.isplayingtag.setVisibility(View.VISIBLE); } else { holder.isplayingtag.setVisibility(View.INVISIBLE); } holder.itemView.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { if (mTabs!=null){ mTabs.setLeaveTag(); } setFocusIndex(position); } } }); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {//主动播放某个资产 playvideo(mTabs.getViewPos(), position); } }); holder.itemView.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT && event.getAction() == KeyEvent.ACTION_DOWN) { if (mNewsVideoLayout!=null){ mNewsVideoLayout.requestFocus(); } return true; } else if (position == 0 && keyCode == KeyEvent.KEYCODE_DPAD_UP) { holder.itemView.startAnimation(shakeAnim); return true; } else if (position == getItemCount() - 1 && keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { holder.itemView.startAnimation(shakeAnim); return true; } return false; } }); } /** * 设置正在播放tag * * @return */ private void showIsPlayingTag(ItemViewHolder viewHolder, int curposition) { if (curPlayingTabIndex != mTabs.getViewPos()) {//连播时当显示的列表和播放器联播的资产列表不同时,直接返回,避免crash isPlayingIndex = curposition; //更新正在播放位置 return; } if (null != mLinearLayoutManager.findViewByPosition(isPlayingIndex)) { mLinearLayoutManager.findViewByPosition(isPlayingIndex).findViewById(R.id.isplaying).setVisibility(View.INVISIBLE); } if (null != viewHolder) { viewHolder.isplayingtag.setVisibility(View.VISIBLE);//显示点击item的正在播放tag } isPlayingIndex = curposition;//更新正在播放位置 } /** * 时间计算差 * * @return */ private String calDateTime(String time) { try { date = format.parse(time); } catch (ParseException e) { e.printStackTrace(); } return RelativeDateUtils.format(date, curDate); } @Override public int getItemCount() { return assetElements == null ? 0 : assetElements.size(); } class ItemViewHolder extends RecyclerView.ViewHolder { SimpleDraweeView simpleDraweeView; // ImageView simpleDraweeView; TextView title; TextView timetag; TextView isplayingtag; public ItemViewHolder(final View itemview) { super(itemview); itemview.setFocusable(true); simpleDraweeView = (SimpleDraweeView) itemview.findViewById(R.id.netease_news_list_pic); // simpleDraweeView = (ImageView) itemview.findViewById(R.id.netease_news_list_pic); title = (TextView) itemview.findViewById(R.id.netease_news_title); timetag = (TextView) itemview.findViewById(R.id.netease_news_time); isplayingtag = (TextView) itemview.findViewById(R.id.isplaying); } } } }