package com.wasu.cs.ui; import android.annotation.SuppressLint; import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; import android.os.Handler.Callback; import android.os.Message; import android.support.annotation.Nullable; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewStub; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.AdapterView; import android.widget.ImageView; import android.widget.TextView; import com.wasu.cs.adapter.GridExAdapterBase; import com.wasu.cs.model.CatData; import com.wasu.cs.model.CatData.Element; import com.wasu.cs.model.Model; import com.wasu.cs.module.CornerMarkModule; import com.wasu.cs.protocol.BaseListProtocol; import com.wasu.cs.protocol.CatProtocol; import com.wasu.cs.widget.BlockLinearLayout; import com.wasu.cs.widget.FocusGridViewEx; import com.wasu.frescoimagefetchermodule.FrescoImageFetcherModule; import com.wasu.module.log.WLog; import java.util.List; import cn.com.wasu.main.BuildConfig; import cn.com.wasu.main.ChannelFlavor; import cn.com.wasu.main.IntentMap; import cn.com.wasu.main.LayoutCodeMap; import cn.com.wasu.main.R; /** * 电影、电视剧、少儿、娱乐、音乐等的二级列表的container的内容填充部分 * 包括推荐广告位置,和资产位置 * Created by LiuYang on 6/30/15. */ public class FragmentChannelMovieHome extends FragmentPageBase implements OnScrollListener{ private static final int GridColNum = 6; private static final String TAG = FragmentChannelMovieHome.class.getSimpleName(); private static final int ResumeRequestsMSG = 1; private FragmentBlockRecommend mBlockRecommend; private FocusGridViewEx mGridView; private ChannelMovieHomeAdapter mAdapter; private BlockLinearLayout mBlockFrameLayout; private CatProtocol mMoreProtocol; private LayoutInflater lInflater; private View vsRecommendBlock; private int position; private boolean isInited=false; private boolean recommendShowed = false; private boolean updateDataed = false; /**标志GridView是否在滚动**/ private static boolean isScrolling = false; private FocusGridViewEx.FocusGridViewColumnListener onGridClumnListener; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater,container,savedInstanceState); View rootView = inflater.inflate(R.layout.fragment_channel_movie_home, container, false); mGridView = (FocusGridViewEx)rootView.findViewById(R.id.gridView); mBlockFrameLayout = (BlockLinearLayout) rootView.findViewById(R.id.blockFrame); mBlockFrameLayout.setOnFocusSearchListener(mOnFocusSearchListener); mBlockFrameLayout.setOnChildFocusListener(mOnChildFocusListener); // mBlockRecommend = (FragmentBlockRecommend) getChildFragmentManager() // .findFragmentById(R.id.recommendBlock); vsRecommendBlock = (ViewStub)rootView.findViewById(R.id.vsRecommendBlock); vsRecommendBlock.setVisibility(View.GONE); initGridView(); return rootView; } @Override protected boolean onBackPressed() { if(recommendShowed){ //说明vsRecommendBlock已经被inflate,有推荐位显示 if(mGridView != null && mBlockRecommend!=null){ if(mBlockRecommend.getView().hasFocus()) { mBlockRecommend.onBackPressed(); } else if(mGridView.hasFocus() && mAdapter.getCount() > 0){ mGridView.scrollTo(0, 0); mGridView.reset(); mGridView.setSelection(0); mBlockRecommend.onBackPressed(); }}else{ WLog.d(TAG, "mGridView == null 被强制GC"); } }else{ //没有推荐位 if(mGridView != null){ mGridView.scrollTo(0, 0); mGridView.reset(); mGridView.setSelection(0); }else{ WLog.d(TAG, "mGridView == null 被强制GC"); } } return false; } @Override public void onUnSelected() { super.onUnSelected(); hideLoading(); } @Override public void onSelected() { super.onSelected(); if(!isInited && getUserVisibleHint()){ showLoading(); }else { hideLoading(); // 2017/1/15 Add By Frewen.Wong 针对乐视电视的焦点错乱的问题继续宁特殊处理 if (BuildConfig.FLAVOR.equalsIgnoreCase(ChannelFlavor.LETV_MARKET)) { if (recommendShowed && mGridView.hasFocus()) { //说明vsRecommendBlock已经被inflate,有推荐位显示 mGridView.scrollTo(0, 0); mGridView.reset(); mGridView.setSelection(0); View view = mBlockRecommend.focusSearch(mGridView, View.FOCUS_UP); view.requestFocus(); mBlockRecommend.focusSearch(view, View.FOCUS_UP); } } } } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); if(mAdapter == null){ mAdapter = new ChannelMovieHomeAdapter(); } mGridView.setAdapter(mAdapter); //给GridView添加到达左右两边的监听 mGridView.setOnGridViewColumnListener(onGridClumnListener); fetchData(); } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isVisibleToUser && !isInited && mCatData != null && mGridView != null){ isInited = true; updateData(mCatData); }else if(!isVisibleToUser){ hideLoading(); } } /** * 获取二级列表页container的数据,包括资产、推荐和广告 */ @Override public void onFetchData(final CatData catData) { if (catData == null){ WLog.d(TAG, "onFetchData中传入的catData为null"); return;} mCatData = catData; isInited = (catData.getAssets().size() > 0); updateData(catData); } private void updateData(CatData catData){ if (catData == null){ WLog.d(TAG, "updateData中传入的catData为null,数据更新失败"); return; } String url = ""; // getChildFragmentManager().beginTransaction().hide(mBlockRecommend).commit(); setGridViewCanFocus(true); if(getLayoutCode().equalsIgnoreCase(LayoutCodeMap.RECOMMEND_MOVIE) || getLayoutCode().equalsIgnoreCase(LayoutCodeMap.RECOMMEND_NEWS)) { // getChildFragmentManager().beginTransaction().show(mBlockRecommend).commit(); if(vsRecommendBlock instanceof ViewStub){ ((ViewStub)vsRecommendBlock).inflate(); } mBlockRecommend = (FragmentBlockRecommend) getChildFragmentManager() .findFragmentById(R.id.recommendBlock); setGridViewCanFocus(false); mBlockRecommend.initData(catData,getLayoutCode()); List elements = catData.getElements(); if(elements != null && 2 < elements.size()) { url = elements.get(2).getJsonUrl(); } recommendShowed = true; } else if(getLayoutCode().equalsIgnoreCase(LayoutCodeMap.MOVIE_LIST) || getLayoutCode().equalsIgnoreCase(LayoutCodeMap.NEWS_LIST) || getLayoutCode().equalsIgnoreCase("News_Subject_TP1")) { recommendShowed = false; mAdapter.setData(catData.getAssets()); mAdapter.notifyDataSetChanged(); /**在ViewPager向右滑动切换时保证左边一屏第一排最后一个item被选中**/ if(!FragmentBlockHeader.headerFocused && !recommendShowed && FragmentBlockHeader.viewpagerRightSlide){ if(null != mGridView){ if(mAdapter != null && mAdapter.getCount()>=6){ mGridView.setSelectedViewIndex(5); }else if(mAdapter != null && mAdapter.getCount()>0){ mGridView.setSelectedViewIndex(mAdapter.getCount()-1); }else{ } }else{ } } } else if(getLayoutCode().equalsIgnoreCase("SubjectList")) { recommendShowed = false; if (catData.getElements()!=null && catData.getElements().size()>0 && catData.getElements().get(0) != null && catData.getElements().get(0).getJsonUrl() != null) { url = catData.getElements().get(0).getJsonUrl(); } } else { if (catData.getCat() != null && catData.getCat().getAssetListUrl() != null) { url = catData.getCat().getAssetListUrl(); } } if(!TextUtils.isEmpty(url)) { updateDataed = false; initGridData(url); }else{ updateDataed = true; } hideLoading(); } @Override public void onDestroyView() { super.onDestroyView(); updateDataed = false; isInited = false; if(mGridView != null){ mGridView = null; } if(mBlockFrameLayout != null){ mBlockFrameLayout.removeAllViews(); mGridView = null; } if(mMoreProtocol != null){ mMoreProtocol = null; } if(lInflater != null){ lInflater = null; } if(vsRecommendBlock != null){ vsRecommendBlock = null; } if(mAdapter != null){ mAdapter.clearData(); mAdapter = null; } if(mHandler2 != null){ mHandler2.removeMessages(ResumeRequestsMSG); mHandler2.removeCallbacksAndMessages(null); } if(mBlockRecommend != null){ mBlockRecommend.cleanResource(); mBlockFrameLayout.removeAllViews(); mBlockFrameLayout = null; } } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); } @SuppressLint("NewApi") private void initGridView() { mGridView.setTag("tag"+position); lInflater = LayoutInflater.from(getActivity()); mGridView.setNumColumns(GridColNum); mGridView.setFocusHightlightDrawable(R.drawable.tv_select_focus); mGridView.postAnimation(200, null); mGridView.setFocusRealId(R.id.ivPic); mGridView.setFocusShadowDrawable(R.drawable.focus_shadow); // mGridView.setOnScrollListener(new PauseOnScrollListener(FrescoImageFetcherModule.getInstance().getImageLoader(), true, true)); /** * item点击监听器 */ mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView adapterView, View view, int i, long l) { String josnUrl = ((CatData.AssetElement)mGridView.getAdapter().getItem(i)).getJsonUrl(); String layoutCode = ((CatData.AssetElement)mGridView.getAdapter().getItem(i)).getLayout(); IntentMap.startIntent(getActivity(),null,layoutCode,josnUrl,null); } }); mGridView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView adapterView, View view, int i, long l) { checkNextPageData(i); } @Override public void onNothingSelected(AdapterView adapterView) { } }); mMoreProtocol = new CatProtocol(); mGridView.setOnScrollListener(this); //mGridView.setOnGridViewColumnListener(); } @Override public void setArguments(Bundle args) { position = args.getInt("position",-2); super.setArguments(args); } /** * * @param focus */ private void setGridViewCanFocus(boolean focus) { mGridView.setFocusable(focus); mGridView.setVerticalScrollBarEnabled(focus); } /** * 只会在带有推荐位的列表页才回调用,没有推荐位的列表在Fragment初始化的时候就已经把gridview加载完成了 * @param url */ private void initGridData(String url) { mMoreProtocol.fetchData(getHandler(), url, new BaseListProtocol.DataFetchCallback() { @Override public void onResult(boolean successed, Model data) { if (successed) { CatData catData = (CatData) data; if (catData != null) { mAdapter.setData(catData.getAssets()); mAdapter.notifyDataSetChanged(); } if(mAdapter.getCount()>0){ mBlockRecommend.setAssetGridViewItemEmpty(false); updateDataed = true; }else{ mBlockRecommend.setAssetGridViewItemEmpty(true); } } else { } } }); } private void checkNextPageData(int position) { int count = mAdapter.getCount(); if(getProtocol().getTotalSize() > count && position > count / 2){ getProtocol().nextPage(); } } /** * 控制焦点 */ private final BlockLinearLayout.OnFocusSearchListener mOnFocusSearchListener = new BlockLinearLayout.OnFocusSearchListener() { @Override public View onFocusSearch(final View focused, int direction) { // if headers is running transition, focus stays View res = null; if(mBlockRecommend != null && mGridView != null) { if(mGridView.hasFocus()){ //GridView 进行焦点处理 // 1:已经在最后一行,再向下,焦点还应该在刚才的view // 2: 已经在第一行,再向上, 焦点应该移交到更上面的view // 3: 已经在最左边,再向左, 焦点还应该在刚才的view //4: 已经在最邮编,再向右, 切换到另外一页 if(direction == View.FOCUS_UP){ View focusView = mBlockRecommend.focusSearch(focused,direction); if(focusView == null || focusView instanceof FocusGridViewEx){ mGridView.setFocusableInTouchMode(true); setGridViewCanFocus(true); gridViewRequestFocus(); res = mGridView; }else { res = focusView; } }else if(direction == View.FOCUS_DOWN){ res = mGridView; }else if(direction == View.FOCUS_LEFT){ res = mGridView; }else if(direction == View.FOCUS_RIGHT){ //donothing } }else{ //其他控件获得焦点也自己处理自己的焦点边界事件 (可以认为是 mBlockRecommend 获得焦点) setGridViewCanFocus(false); if(direction == View.FOCUS_UP){ View focusView = mBlockRecommend.focusSearch(focused,direction); if(focusView != null){ res = focusView; } }else if(direction == View.FOCUS_DOWN){ View focusView = mBlockRecommend.focusSearch(focused,direction); if(focusView == null){ mGridView.setFocusableInTouchMode(true); setGridViewCanFocus(true); gridViewRequestFocus(); res = mGridView; }else { res = focusView; } }else if(direction == View.FOCUS_LEFT){ //do nothing }else if(direction == View.FOCUS_RIGHT){ //do nothing } } // if(direction == View.FOCUS_DOWN && mGridView.hasFocus()){ // WLog.e("jeepc","---810---"); // res = mGridView; // } else { // WLog.e("jeepc","---820---"); // View focusView = mBlockRecommend.focusSearch(focused,direction); // WLog.e("jeepc",focused==null?"null":focused.toString()); // WLog.e("jeepc",focusView==null?"null":focusView.toString()); // WLog.e("jeepc","------------------------------"); // if(focusView != null) { // WLog.e("jeepc","---821---"); // res = focusView; // setGridViewCanFocus(false); // } else if(direction == View.FOCUS_DOWN){ // WLog.e("jeepc","---825---"); // mGridView.setFocusableInTouchMode(true); // setGridViewCanFocus(true); //// mGridView.requestFocus(); // gridViewRequestFocus(); // res = mGridView; // } // } // if(direction == View.FOCUS_LEFT && mGridView.hasFocus()){ // res = mGridView; // } } else{ // if(direction == View.FOCUS_DOWN){ // WLog.e("jeepc","---901---"); // res = mGridView; // } } return res; } }; /** * 从首页的推荐位跳转焦点到gridview的时候避免总是gridview得第一份item获得焦点 */ private void gridViewRequestFocus(){ if(mGridView.getChildCount()>=6){ int index = mBlockRecommend.getRecommendSelectedIndex(); if(mBlockRecommend.mIsNews){ if(0==index){ mGridView.setSelectedViewIndex(0); }else if(1==index){ mGridView.setSelectedViewIndex(2); }else if(2==index){ mGridView.setSelectedViewIndex(3); }else{ mGridView.setSelectedViewIndex(5); } }else{ if(0==index){ mGridView.setSelectedViewIndex(0); }else if(1==index){ mGridView.setSelectedViewIndex(1); }else if(2==index){ mGridView.setSelectedViewIndex(2); }else if(3==index){ mGridView.setSelectedViewIndex(3); }else if(4==index){ mGridView.setSelectedViewIndex(4); }else{ mGridView.setSelectedViewIndex(5); } } }else{ mGridView.requestFocus(); } } /** * 焦点改变监听器 */ private final BlockLinearLayout.OnChildFocusListener mOnChildFocusListener = new BlockLinearLayout.OnChildFocusListener() { @Override public boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { boolean res = false; if (getChildFragmentManager().isDestroyed()) { res = true; } else if (null != mBlockRecommend && mBlockRecommend.requestFocus(direction, previouslyFocusedRect)) { res = true; } else if (mGridView.requestFocus(direction, previouslyFocusedRect)) { res = true; } return res; }; @Override public void onRequestChildFocus(View child, View focused) { if (getChildFragmentManager().isDestroyed()) { return; } } }; public void showLoading(){ ActivityBase baseActivity = (ActivityBase) getActivity(); if (baseActivity != null){ baseActivity.showLoading(); } } public void hideLoading(){ ActivityBase baseActivity = (ActivityBase) getActivity(); if (baseActivity != null){ baseActivity.hideLoading(); } } private final Handler mHandler2 = new Handler(new Callback() { @Override public boolean handleMessage(Message msg) { switch (msg.what) { case ResumeRequestsMSG: if(getActivity() != null){ isScrolling = false; onScrollStateChanged(mGridView, SCROLL_STATE_IDLE); } break; default: break; } return false; } }); public void setOnGridClumnListener(FocusGridViewEx.FocusGridViewColumnListener onGridClumnListener) { this.onGridClumnListener = onGridClumnListener; } class ChannelMovieHomeAdapter extends GridExAdapterBase { //定义当前listview是否在滑动状态 private boolean scrollState=false; public void setScrollState(boolean scrollState) { this.scrollState = scrollState; } @SuppressLint("NewApi") @Override public View getView(int position, View convertView, ViewGroup viewGroup) { isScrolling = true; if(convertView != null){ // if(mGridView.isOnMeasure){ // return convertView; // } String tag = String.valueOf(convertView.getTag(R.id.tag_second01)); if(!TextUtils.isEmpty(tag)){ if(tag.equalsIgnoreCase(String.valueOf(position))){ return convertView; } } } onScrollStateChanged(mGridView, SCROLL_STATE_TOUCH_SCROLL); mHandler2.removeMessages(ResumeRequestsMSG); mHandler2.sendEmptyMessageDelayed(ResumeRequestsMSG, 500); final CatData.AssetElement itemData = (CatData.AssetElement) getItemData(position); ViewHolder viewHolder = null; if(null == convertView){ viewHolder = new ViewHolder(); convertView = lInflater.inflate(R.layout.item_gridview, null); viewHolder.vImage = (ImageView) convertView.findViewById(R.id.ivPic); viewHolder.tvName = (TextView) convertView.findViewById(R.id.name); viewHolder.tvScore = (TextView) convertView.findViewById(R.id.tvScore); viewHolder.ivCorner = (ImageView) convertView.findViewById(R.id.ivCoener); convertView.setContentDescription(String.valueOf(position)); convertView.setTag(R.id.tag_first01,viewHolder); }else{ viewHolder = (ViewHolder) convertView.getTag(R.id.tag_first01); /**防止快速滚动gridview图片显示错位**/ // viewHolder.vImage.setImageDrawable(null); // viewHolder.tvName.setText(null); } if(null != itemData){ viewHolder.tvName.setText(itemData.getTitle()); //不管是否在滚动,item的name都显示 /****在滚动的时候不现实图片只显示name****/ if(!scrollState){//如果当前不是滑动的状态,我们填充真数据 FrescoImageFetcherModule.getInstance().attachImage(itemData.getPicUrl(), viewHolder.vImage); viewHolder.vImage.setTag("1"); }else{ //如果当前是滑动的状态,我们填充假数据 viewHolder.vImage.setImageResource(R.drawable.default_pic_loading); viewHolder.vImage.setTag(itemData.getPicUrl()); //将数据image_url保存在Tag当中 } if(!TextUtils.isEmpty(itemData.getPoints())){ viewHolder.tvScore.setVisibility(View.VISIBLE); viewHolder.tvScore.setText(itemData.getPoints()); }else{ viewHolder.tvScore.setVisibility(View.GONE); } if(!TextUtils.isEmpty(itemData.getCmark())){ String cMarkPicUrl = CornerMarkModule.getInstance().getCornerMarkPicUrl(itemData.getCmark()); if(null != cMarkPicUrl){ FrescoImageFetcherModule.getInstance().attachImage(cMarkPicUrl, viewHolder.ivCorner); viewHolder.ivCorner.setVisibility(View.VISIBLE); } }else{ viewHolder.ivCorner.setVisibility(View.GONE); } } convertView.setTag(R.id.tag_second01,position); return convertView; } } static class ViewHolder{ ImageView vImage; TextView tvName; TextView tvScore; ImageView ivCorner; } /*********GridView滚动监听器************/ @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // TODO Auto-generated method stub } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { // TODO Auto-generated method stub switch (scrollState){ case AbsListView.OnScrollListener.SCROLL_STATE_IDLE://停止滚动 { //设置为停止滚动 mAdapter.setScrollState(false); //当前屏幕中listview的子项的个数 int count = view.getChildCount(); for (int i = 0; i < count; i++) { if(isScrolling){ /**在显示图片的过程中滚动GridView时跳出循环停止图片显示,避免慢速滚动的时候卡顿**/ break; } /*//获取到item的name TextView tv_name = (TextView) view.getChildAt(i).findViewById(R.id.name);*/ //获取到item的头像 ImageView iv_show= (ImageView) view.getChildAt(i).findViewById(R.id.ivPic); //取消在滚动的时候不显示name /* if (tv_name.getTag() != null) { //非null说明需要加载数据 tv_name.setText(tv_name.getTag().toString());//直接从Tag中取出我们存储的数据name并且赋值 tv_name.setTag(null);//设置为已加载过数据 }*/ if (!iv_show.getTag().equals("1")){//!="1"说明需要加载数据 String image_url=iv_show.getTag().toString();//直接从Tag中取出我们存储的数据image——url if(!TextUtils.isEmpty(image_url)){ FrescoImageFetcherModule.getInstance().attachImage(image_url, iv_show); } iv_show.setTag("1");//设置为已加载过数据 }else{ /**图片加载过就跳出本次循环**/ continue; } /**及时回收局部变量**/ /* if(tv_name != null){ tv_name = null; }*/ if(iv_show != null){ iv_show = null; } } break; } case AbsListView.OnScrollListener.SCROLL_STATE_FLING://滚动做出了抛的动作 { //设置为正在滚动 mAdapter.setScrollState(true); break; } case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL://正在滚动 { //设置为正在滚动 mAdapter.setScrollState(true); break; } } } @Override public void onSaveInstanceState(Bundle outState) { //在apk出现意外终止时不保存现场,避免在APK挂掉马上恢复时出现异常 // super.onSaveInstanceState(outState); } }