这几天做了个项目有个页面是关于节目类型的标志设置,一共有三种颜色,可以标志三种类型。每种颜色可以选择不同的类型。如果一个颜色已经选择了一种类型,其他两种颜色相应的类型就要置灰。当焦点移动到这一类型时要跳过。刚打开这个页面时,焦点要跳转到已经选择的类型上。当从上一个颜色切换到下一种颜色时,焦点也要跳转到下一个颜色选择的类型上。节目类型一共11个,三个颜色下的节目类型是一个横向的GridView,焦点切换时,外套的HorizontalScrollView也要滚动到相应位置。还要适配Rtl布局,初始效果如下图:
重点:
1. 第一种颜色已有选中类型的情况下,初始化时,焦点的跳转。
2. 在一种颜色选中一种类型时,下一种颜色该类型的置灰
3. 按左右键时,焦点的跳转及HorizontalScrollView的滚动。
4. 从上一种颜色跳转到下一种颜色时焦点的跳转
5. 当选中一个类型时,焦点跳转,position虽然跳过去了,但焦点还是会跑到这个类型上;
6. 当选中了两个相连的类型时,焦点的跳转(有可能只跳了一格),当选中了最后两个相连的类型时的特殊处理,与选中前面两个类型不同。
7. 当选中了三个相连类型时,焦点跳转(有可能只跳一格,也有可能一格也跳不过去),当选中最后三个相连的类型时的特殊处理。
8. Rtl布局时,GridView的各个项虽然已经左右翻转,但position的位置还是从左边开始的。scrollView的滚动位置需要特别注意。
9. 当每个颜色选中第一项或最后一项以及中间项时,左右箭头的显示;
上代码:
public class EPGTypeDialog extends Dialog { private static final String TAG = "EPGTypeDialog"; public static boolean mHasEditType; GridView epgList,gv_red,gv_blue; HorizontalScrollView hsv_green,hsv_red,hsv_blue; EPGTypeListAdapter listAdapter,redAdapter,blueAdapter; ListmData; private Context mContext; public static TextView tv_orange,tv_blue,tv_red; EPGSaveValue sv; List gridViewList = new ArrayList (); private Handler myHandler = new Handler(); int gridViewIndex = 0;//当前在哪个颜色 int[] selectIndex = new int[3];//选中的三个类型的位置 String[] keyStr = {"orange1","red2","blue3"}; int itemWidth = 0; private ImageView iv_green_left,iv_green_right,iv_red_left,iv_red_right,iv_blue_left,iv_blue_right; public EPGTypeDialog(@NonNull Context context) { super(context); this.mContext = context; sv = EPGSaveValue.getInstance(mContext); } public EPGTypeDialog(@NonNull Context context, int themeResId) { super(context, themeResId); this.mContext = context; sv = EPGSaveValue.getInstance(mContext); } protected EPGTypeDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) { super(context, cancelable, cancelListener); this.mContext = context; sv = EPGSaveValue.getInstance(mContext); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_epgtype_dialog); setWindowPosition(); initUI(); } public void initUI(){ epgList = (GridView)findViewById(R.id.gv_green); gv_red = (GridView)findViewById(R.id.gv_red); gv_blue = (GridView)findViewById(R.id.gv_blue); hsv_green = (HorizontalScrollView)findViewById(R.id.hsv_green); hsv_red = (HorizontalScrollView)findViewById(R.id.hsv_red); hsv_blue = (HorizontalScrollView)findViewById(R.id.hsv_blue); tv_orange = (TextView)findViewById(R.id.type_green); tv_red = (TextView)findViewById(R.id.type_red); tv_blue = (TextView)findViewById(R.id.type_blue); iv_green_left = (ImageView)findViewById(R.id.iv_green_left); iv_green_right = (ImageView)findViewById(R.id.iv_green_right); iv_red_left = (ImageView)findViewById(R.id.iv_red_left); iv_red_right = (ImageView)findViewById(R.id.iv_red_right); iv_blue_left = (ImageView)findViewById(R.id.iv_blue_left); iv_blue_right = (ImageView)findViewById(R.id.iv_blue_right); listAdapter = new EPGTypeListAdapter(mContext,epgList); redAdapter = new EPGTypeListAdapter(mContext,gv_red); blueAdapter = new EPGTypeListAdapter(mContext,gv_red); mData = listAdapter.loadEPGFilterTypeData(""); gridViewList.add(epgList); gridViewList.add(gv_red); gridViewList.add(gv_blue); listAdapter.setGridViewList(gridViewList); redAdapter.setGridViewList(gridViewList); blueAdapter.setGridViewList(gridViewList); listAdapter.setEPGData(mData); redAdapter.setEPGData(mData); blueAdapter.setEPGData(mData); listAdapter.setSource(1); redAdapter.setSource(2); blueAdapter.setSource(3); if(mData != null){ epgList.setAdapter(listAdapter); gv_red.setAdapter(redAdapter); gv_blue.setAdapter(blueAdapter); tv_orange.setText(mData.get(0).getData()); tv_red.setText(mData.get(0).getData()); tv_blue.setText(mData.get(0).getData()); } //横向gridview int length = 138; int size = 0; if(mData != null && mData.size() != 0){ size = mData.size(); } DisplayMetrics dm = mContext.getResources().getDisplayMetrics(); float density = dm.density; int gridviewWidth = (int)(size *(length +12)*density); itemWidth = (int)(length*density); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(gridviewWidth, ViewGroup.LayoutParams.FILL_PARENT); epgList.setLayoutParams(params); epgList.setColumnWidth(itemWidth); epgList.setNumColumns(size); epgList.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if(event.getAction() == KeyEvent.ACTION_DOWN){ if(listAdapter.ismFocus()){ listAdapter.onMainKey(v,keyCode); int mPosition = 0; if(isRtl()){ //rtl布局下,GridView的位置顺序相反 mPosition = mData.size()-1-EPGTypeListAdapter.mPosition; }else{ mPosition = EPGTypeListAdapter.mPosition; } //操作外套scrollView的滑动位置和两边箭头显示与隐藏 switch (keyCode){ case KeyEvent.KEYCODE_DPAD_RIGHT: int scrollWidth1 = itemWidth * mPosition; //smoothScrollTo指滑动到的位置,smoothScrollBy指滑动的距离 hsv_green.smoothScrollTo(scrollWidth1,0); if(EPGTypeListAdapter.mPosition == mData.size()-1){//ltr iv_green_right.setVisibility(View.INVISIBLE); }else if(EPGTypeListAdapter.mPosition == 0){//rtl iv_green_left.setVisibility(View.INVISIBLE); }else{ iv_green_left.setVisibility(View.VISIBLE); iv_green_right.setVisibility(View.VISIBLE); } break; case KeyEvent.KEYCODE_DPAD_LEFT: int scrollWidth = itemWidth * mPosition; hsv_green.smoothScrollTo(scrollWidth,0); if(EPGTypeListAdapter.mPosition == 0){//ltr iv_green_left.setVisibility(View.INVISIBLE); }else if(EPGTypeListAdapter.mPosition == mData.size() -1){//rtl iv_green_right.setVisibility(View.INVISIBLE); }else{ iv_green_left.setVisibility(View.VISIBLE); iv_green_right.setVisibility(View.VISIBLE); } break; } } } return false; } }); gv_red.setLayoutParams(params); gv_red.setColumnWidth(itemWidth); gv_red.setNumColumns(size); gv_red.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if(event.getAction() == KeyEvent.ACTION_DOWN){ if(redAdapter.ismFocus()){ redAdapter.onMainKey(v,keyCode); int mPosition = 0; if(isRtl()){ //rtl布局下,GridView的位置顺序相反 mPosition = mData.size()-1-EPGTypeListAdapter.mPosition; }else{ mPosition = EPGTypeListAdapter.mPosition; } //操作外套scrollView的滑动位置和两边箭头显示与隐藏 int scrollWidth = 0; switch (keyCode){ case KeyEvent.KEYCODE_DPAD_RIGHT: scrollWidth = itemWidth * mPosition; //smoothScrollTo指滑动到的位置,smoothScrollBy指滑动的距离 hsv_red.smoothScrollTo(scrollWidth,0); if(EPGTypeListAdapter.mPosition == mData.size()-1){//ltr iv_red_right.setVisibility(View.INVISIBLE); }else if(EPGTypeListAdapter.mPosition == 0){//rtl iv_red_left.setVisibility(View.INVISIBLE); }else{ iv_red_left.setVisibility(View.VISIBLE); iv_red_right.setVisibility(View.VISIBLE); } break; case KeyEvent.KEYCODE_DPAD_LEFT: scrollWidth = itemWidth * mPosition; hsv_red.smoothScrollTo(scrollWidth,0); if(EPGTypeListAdapter.mPosition == 0){//ltr iv_red_left.setVisibility(View.INVISIBLE); }else if(EPGTypeListAdapter.mPosition == mData.size() -1){//rtl iv_red_right.setVisibility(View.INVISIBLE); }else{ iv_red_left.setVisibility(View.VISIBLE); iv_red_right.setVisibility(View.VISIBLE); } break; } } } return false; } }); gv_blue.setLayoutParams(params); gv_blue.setColumnWidth(itemWidth); gv_blue.setNumColumns(size); gv_blue.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if(event.getAction() == KeyEvent.ACTION_DOWN){ if(blueAdapter.ismFocus()){ blueAdapter.onMainKey(v,keyCode); int mPosition = 0; if(isRtl()){ //rtl布局下,GridView的位置顺序相反 mPosition = mData.size()-1-EPGTypeListAdapter.mPosition; }else{ mPosition = EPGTypeListAdapter.mPosition; } //操作外套scrollView的滑动位置和两边箭头显示与隐藏 int scrollWidth = 0; switch (keyCode){ case KeyEvent.KEYCODE_DPAD_RIGHT: scrollWidth = itemWidth * mPosition; //smoothScrollTo指滑动到的位置,smoothScrollBy指滑动的距离 hsv_blue.smoothScrollTo(scrollWidth,0); if(EPGTypeListAdapter.mPosition == mData.size()-1){//ltr iv_blue_right.setVisibility(View.INVISIBLE); }else if(EPGTypeListAdapter.mPosition == 0){//rtl iv_blue_left.setVisibility(View.INVISIBLE); }else{ iv_blue_left.setVisibility(View.VISIBLE); iv_blue_right.setVisibility(View.VISIBLE); } break; case KeyEvent.KEYCODE_DPAD_LEFT: scrollWidth = itemWidth * mPosition; hsv_blue.smoothScrollTo(scrollWidth,0); if(EPGTypeListAdapter.mPosition == 0){//ltr iv_blue_left.setVisibility(View.INVISIBLE); }else if(EPGTypeListAdapter.mPosition == mData.size() -1){//rtl iv_blue_right.setVisibility(View.INVISIBLE); }else{ iv_blue_left.setVisibility(View.VISIBLE); iv_blue_right.setVisibility(View.VISIBLE); } break; } } } return false; } }); initUIValue(); } int firstSeled = 0;//第一个颜色默认选中的位置 public void initUIValue(){ selectIndex[0] = getSelectGrid("orange1"); EPGTypeListAdapter.mPosition = selectIndex[0]; epgList.requestFocus(); if(isRtl()){ firstSeled = mData.size()-1-selectIndex[0]; }else{ firstSeled = selectIndex[0]; } if(selectIndex[0] != 0){//本判断条件为阿拉伯语时添加 myHandler.postDelayed(new Runnable() { @Override public void run() { epgList.setSelection(selectIndex[0]); //这一句不能用myHandler.postAtFrontOfQueue hsv_green.smoothScrollTo(itemWidth * firstSeled,0); } },100); } //arrow display if(selectIndex[0] == 0){ iv_green_left.setVisibility(View.INVISIBLE); }else if(selectIndex[0] == mData.size()-1){ iv_green_right.setVisibility(View.INVISIBLE); }else{ iv_green_right.setVisibility(View.VISIBLE); iv_green_left.setVisibility(View.VISIBLE); } } /* * 获取各个颜色选中值的位置 * */ public int getSelectGrid(String key){ String offString = mContext.getResources().getString(R.string.nav_sleep_off); for(int i=0;i = 0){ final int index = i-1; gridViewList.get(index).requestFocus(); selectIndex[index] = getSelectGrid(keyStr[index]); EPGTypeListAdapter.mPosition = selectIndex[index]; int firstIndex = 0; if(isRtl()){ firstIndex = mData.size()-1-selectIndex[index]; }else{ firstIndex = selectIndex[index]; } myHandler.postAtFrontOfQueue(new Runnable() { @Override public void run() { gridViewList.get(index).setSelection(selectIndex[index]); } }); if(i == 2){ hsv_red.smoothScrollTo(itemWidth*firstIndex,0); if(selectIndex[index] == 0){ iv_red_left.setVisibility(View.INVISIBLE); }else if(selectIndex[index] == mData.size()-1){ iv_red_right.setVisibility(View.INVISIBLE); //左箭头初始状态不显示,当按上键到当前颜色的选中位置(非第一个位置)时,左箭头要显示出来 iv_red_left.setVisibility(View.VISIBLE); }else{ iv_red_right.setVisibility(View.VISIBLE); iv_red_left.setVisibility(View.VISIBLE); } }else if(i==1){ hsv_green.smoothScrollTo(itemWidth*firstIndex,0); if(selectIndex[index] == 0){ iv_green_left.setVisibility(View.INVISIBLE); }else if(selectIndex[index] == mData.size()-1){ iv_green_right.setVisibility(View.INVISIBLE); //左箭头初始状态不显示,当按上键到当前颜色的选中位置(非第一个位置)时,左箭头要显示出来 iv_green_left.setVisibility(View.VISIBLE); }else{ iv_green_right.setVisibility(View.VISIBLE); iv_green_left.setVisibility(View.VISIBLE); } } } } if(gridViewIndex > 0){ gridViewIndex --; } return true; default: break; } return super.onKeyDown(keyCode, event); } }
布局文件:
EPGTypeListAdapter代码:
package com.example.demo1.demo1.epgtype; import android.content.Context; import android.os.Handler; import android.text.TextUtils; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.LinearLayout; import android.widget.TextView; import com.example.demo1.demo1.R; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; /** * Created by wangchunmei.ex on 2018/10/12. */ public class EPGTypeListAdapter extends BaseAdapter { private static final String TAG = "EPGTypeListAdapter"; ListmData; Context mContex; EPGSaveValue sv; GridView mList; List gridViewList; ViewHolder mViewHoler; static int mPosition = 0; private static boolean mFocus = true; int source = 0; String offString = ""; EPGTypeListAdapter(Context context){ mContex = context; sv = EPGSaveValue.getInstance(context); } EPGTypeListAdapter(Context context,GridView mainList){ mContex = context; sv = EPGSaveValue.getInstance(context); mList = mainList; mPosition = 0; mFocus = true; offString = mContex.getResources().getString(R.string.nav_sleep_off); } public boolean ismFocus(){ return mFocus; } @Override public int getCount() { if(mData == null) return 0; return mData.size(); } @Override public Object getItem(int position) { return mData == null? null : position; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if(convertView == null){ mViewHoler = new ViewHolder(); convertView = LayoutInflater.from(mContex).inflate(R.layout.epg_type_item,null); mViewHoler.mTextView = (TextView)convertView.findViewById(R.id.epg_type_name); convertView.setTag(mViewHoler); }else{ mViewHoler = (ViewHolder)convertView.getTag(); } if(mData != null && mData.size() >0){ if(null != mData.get(position) && mData.get(position).data.length() != 0){ if(mViewHoler.mTextView != null){ mViewHoler.mTextView.setText(mData.get(position).data); //每个颜色显示选中的类型值,并将选中的项设置成蓝色 if(sv.readBooleanValue(mData.get(position).data,false) && sv.readIntValue(mData.get(position).data,0)==source){ mViewHoler.mTextView.setTextColor(mContex.getResources().getColor(R.color.app_panel_tab_select)); if(source == 1){ EPGTypeDialog.tv_orange.setText(mData.get(position).data); }else if(source == 2){ EPGTypeDialog.tv_red.setText(mData.get(position).data); }else if(source == 3){ EPGTypeDialog.tv_blue.setText(mData.get(position).data); } }else{ //将每个颜色中其他颜色已经选中的类型置灰,其他类型恢复默认 if(source == 1){ selectIndex[1] = getSelectGrid(keyStr[1]); selectIndex[2] = getSelectGrid(keyStr[2]); if((position == selectIndex[1] || position == selectIndex[2]) && position != 0){ mViewHoler.mTextView.setTextColor(mContex.getResources().getColor(R.color.card_meta_text_color_disabled)); mViewHoler.mTextView.setBackgroundColor(mContex.getResources().getColor(R.color.banner_basic_divider)); }else{ mViewHoler.mTextView.setTextColor(mContex.getResources().getColor(R.color.white)); } }else if(source == 2){ selectIndex[0] = getSelectGrid(keyStr[0]); selectIndex[2] = getSelectGrid(keyStr[2]); if((position == selectIndex[0] || position == selectIndex[2]) && position != 0){ mViewHoler.mTextView.setTextColor(mContex.getResources().getColor(R.color.card_meta_text_color_disabled)); mViewHoler.mTextView.setBackgroundColor(mContex.getResources().getColor(R.color.banner_basic_divider)); }else{ mViewHoler.mTextView.setTextColor(mContex.getResources().getColor(R.color.white)); } }else if(source == 3){ selectIndex[0] = getSelectGrid(keyStr[0]); selectIndex[1] = getSelectGrid(keyStr[1]); if((position == selectIndex[0] || position == selectIndex[1]) && position != 0){ mViewHoler.mTextView.setTextColor(mContex.getResources().getColor(R.color.card_meta_text_color_disabled)); mViewHoler.mTextView.setBackgroundColor(mContex.getResources().getColor(R.color.banner_basic_divider)); }else{ mViewHoler.mTextView.setTextColor(mContex.getResources().getColor(R.color.white)); } } } } } } return convertView; } class ViewHolder{ TextView mTextView; } int[] selectIndex = new int[3]; String[] keyStr = {"orange1","red2","blue3"}; private Handler myHandler = new Handler(); public int getSelectGrid(String key){ for(int i=0;i gridList){ this.gridViewList = gridList; } public void setSource(int source) { this.source = source; } public List getEPGData() { return mData; } public void setEPGData(List mData) { this.mData = mData; } /* * 获取TYPE的值 * */ public List loadEPGFilterTypeData(String contry) { String[] mType = null; mType = mContex.getResources().getStringArray(R.array.nav_epg_filter_type); List mDataGroup = new ArrayList (); for(int i=0;i list = new ArrayList (); for(int i=0;i<3;i++){ if(i != source-1){ list.add(getSelectGrid(keyStr[i])+""); } } Collections.sort(list); switch (keyCode){ case KeyEvent.KEYCODE_DPAD_RIGHT: if(!isRtl()){ if(mPosition >= mList.getAdapter().getCount()-1){ }else{ mPosition++; for(int j=0;j =0;j--){ //当当前位置已经选中,且不等于第一个位置时, if(mPosition == Integer.parseInt(list.get(j)) && mPosition != 0){ if(getSelectPosition(source) == 3){ mPosition -= 2; }else{ mPosition -=1; } } } myHandler.postAtFrontOfQueue(new Runnable() { @Override public void run() { mList.setSelection(mPosition); } }); } } break; case KeyEvent.KEYCODE_DPAD_LEFT: if(!isRtl()){ if(mPosition <=0){ }else{ mPosition--; //左键的移动位置与右键正好相反 for(int j=list.size()-1;j>=0;j--){ //当当前位置已经选中,且不等于第一个位置时, if(mPosition == Integer.parseInt(list.get(j)) && mPosition != 0){ if(getSelectPosition(source) == 3){ mPosition -= 2; }else{ mPosition -=1; } } } myHandler.postAtFrontOfQueue(new Runnable() { @Override public void run() { mList.setSelection(mPosition); } }); } }else{ if(mPosition >= mList.getAdapter().getCount()-1){ }else{ mPosition++; for(int j=0;j