zoukankan      html  css  js  c++  java
  • Android TV 焦点控制实例

    首先上实例:

    项目工程文件:

     

    界面布局:

    activity_tab.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/fastlane_background"
        android:orientation="vertical"
        tools:context=".activity.TabActivity">
    
    
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_tan"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:descendantFocusability="afterDescendants"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintLeft_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="4"
            android:orientation="horizontal">
    
            <ImageView
                android:id="@+id/main_img"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="2"
                android:background="@drawable/bg_recyclerview_item"
                android:focusable="true"
                android:focusableInTouchMode="true"
                android:padding="15dp"
                android:src="@drawable/pro2"
    
    
    
                />
    
           <!-- <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/main_tab_rv"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="2"/>-->
    
    
            <com.example.focusdome.view.FocusRecyclerView
                android:id="@+id/main_tab_rv"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
    
                />
    
    
        </LinearLayout>
    
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">
    
        <androidx.recyclerview.widget.RecyclerView
    
            android:id="@+id/button_tab_rv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
    
    
            />
        </LinearLayout>
    
    </LinearLayout>

    layout_found_h_recycler_item.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:focusable="true"
        android:background="@drawable/bg_recyclerview_item"
        android:padding="20dp"
        >
    
        <com.example.focusdome.view.CircleImageView
            android:id="@+id/f_h_c_img"
            android:layout_width="109dp"
            android:layout_height="0dp"
            android:layout_gravity="center"
            android:layout_weight="3"
    
            android:src="@drawable/pro5"
    
    
            />
    
    
        <TextView
            android:id="@+id/f_h_c_txt"
            android:layout_width="120dp"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:gravity="center"
            android:text="1111"
            android:textSize="10dp"
            />
    
    
    
    
    
    </LinearLayout>

    layout_main_recycler_txtrecycler.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:focusable="true"
        android:background="@drawable/bg_recyclerview_item"
        >
    
        <TextView
            android:id="@+id/main_rv_rv_txt"
            android:layout_width="match_parent"
            android:layout_height="60dp"
    
    
            android:gravity="center"
            />
    
    
    </LinearLayout>

    layout_recycler_text_item.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:orientation="horizontal"
        android:gravity="center"
        android:background="@drawable/bg_recyclerview_item"
        android:focusable="true">
    
    
        <TextView
            android:id="@+id/tv"
            android:layout_width="120dp"
            android:layout_height="60dp"
            android:textColor="#ffffff"
            android:textSize="16sp"
            android:text=""
            android:padding="10dp"
            android:gravity="center"
            />
    
    </LinearLayout>

    资源文件:

    bg_recyclerview_item.xml

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item android:drawable="@drawable/bg_recyclerview_focus" android:state_selected="true" />
        <item android:drawable="@drawable/bg_recyclerview_focus" android:state_focused="true" />
        <item android:drawable="@drawable/bg_recyclerview_focus" android:state_pressed="true" />
        <item android:drawable="@color/transparent"/>
    </selector>

    bg_recyclerview_focus.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item>
            <shape android:shape="rectangle">
                <solid android:color="#80B469FF" />
                <corners android:radius="10dp" />
            </shape>
        </item>
        <item android:bottom="2dp"
            android:left="2dp"
            android:right="2dp"
            android:top="2dp">
            <shape android:shape="rectangle">
                <solid android:color="#60B469FF" />
                <corners android:radius="8dp" />
            </shape>
        </item>
        <item
            android:bottom="5dp"
            android:left="5dp"
            android:right="5dp"
            android:top="5dp">
            <shape
                android:layout_width="wrap_content"
                android:shape="rectangle">
                <stroke
                    android:width="1dp"
                    android:color="#6672f8" />
            </shape>
        </item>
        <item
            android:bottom="6dp"
            android:left="6dp"
            android:right="6dp"
            android:top="6dp">
            <shape android:shape="rectangle">
                <stroke
                    android:width="1dp"
                    android:color="#6672f8" />
            </shape>
        </item>
    
        <item
            android:bottom="7dp"
            android:left="7dp"
            android:right="7dp"
            android:top="7dp">
            <color android:color="@color/color_141843"/>
        </item>
    </layer-list>

    activity代码:

    package com.example.focusdome.activity;
    
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.core.view.ViewCompat;
    import androidx.recyclerview.widget.LinearLayoutManager;
    import androidx.recyclerview.widget.RecyclerView;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.KeyEvent;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import com.example.focusdome.R;
    import com.example.focusdome.adapter.BtnRecyclerViewAdapter;
    import com.example.focusdome.adapter.MainRecyclerViewAdapter;
    import com.example.focusdome.adapter.MyRecyclerViewAdapter;
    import com.example.focusdome.model.RecyclerMainModel;
    import com.example.focusdome.view.FocusLinearLayoutManager;
    import com.example.focusdome.view.SpaceDecoration;
    
    import java.util.ArrayList;
    
    public class TabActivity extends Activity implements MyRecyclerViewAdapter.OnItemClickListener,MyRecyclerViewAdapter.OnItemFocusChangeListener{
    
        private MyRecyclerViewAdapter adapter;
        private RecyclerView recyclerView;
        private String[] titles = {"首页", "游戏","教育","生活","娱乐","新闻","直播","我的"};
    
        private ImageView imageView;
    
    
        //主体部分
        private MainRecyclerViewAdapter mAdapter;
        private RecyclerView mainRecyclerView;
    
        private ArrayList<RecyclerMainModel> list = new ArrayList<>();
    
    
    
       //底部部分
        private BtnRecyclerViewAdapter btnRecyclerViewAdapter;
        private RecyclerView btnRecyclerView;
    
    
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_tab);
            initView();
            initAdapter();
    
            //初始化主体部分recycle
            mainRecyclerView = findViewById(R.id.main_tab_rv);
    
            list.add(new RecyclerMainModel("第一张",R.drawable.pre));
            list.add(new RecyclerMainModel("第二张",R.drawable.pro));
            list.add(new RecyclerMainModel("第三张",R.drawable.pro2));
            list.add(new RecyclerMainModel("第四张",R.drawable.pro3));
            list.add(new RecyclerMainModel("第五张",R.drawable.pro4));
            list.add(new RecyclerMainModel("第六张",R.drawable.hp_one));
            list.add(new RecyclerMainModel("第七张",R.drawable.hp_four));
            list.add(new RecyclerMainModel("第八张",R.drawable.hp_five));
    
    
            mAdapter = new MainRecyclerViewAdapter(this, list, new MainRecyclerViewAdapter.OnItemClickListener() {
                @Override
                public void onItemClick(View view, int position) {
                    Log.v("点击:", "" + position + view.getId());
    
                    imageView.setImageResource(list.get(position).getM_imgId());
                    //imageView.setScaleType(ImageView.ScaleType.CENTER);
    
    
                }
            }/*, new MainRecyclerViewAdapter.OnItemFocusChangeListener() {
                @Override
                public void onItemFocusChange(View view, int position, boolean hasFocus) {
    
    
                   // Toast.makeText(TabActivity.this,"focus"+position,Toast.LENGTH_LONG).show();
    
                    imageView.setImageResource(list.get(position).getM_imgId());
    
    
                }
            }*/) {
    
                //获得焦点时处理
                @Override
                protected void onItemFocus(View itemView,int positon) {
                   imageView.setImageResource(list.get(positon).getM_imgId());
    
                   System.out.println("获取焦点成功!"+positon);
                    Log.i("view:",itemView.getId()+"23333");
                    itemView.setSelected(true);
                    View view = itemView.findViewById(R.id.main_rv_rv_txt);
    
                    view.setSelected(true);
    
    
                }
                //失去焦点时
    
                @Override
                protected void onItemGetNormal(View itemView) {
                    System.out.println("失去焦点成功!");
                    Log.i("view:",itemView.getId()+"32222");
                   itemView.setSelected(false);
                    View view = itemView.findViewById(R.id.main_rv_rv_txt);
                    view.setSelected(true);
    
    
                }
            };
            FocusLinearLayoutManager linearLayoutManager = new FocusLinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
            mainRecyclerView.setLayoutManager(linearLayoutManager);
            mainRecyclerView.addItemDecoration(new SpaceDecoration(30));
            mainRecyclerView.setAdapter(mAdapter);
    
    
    
            //初始化底部部分
            btnRecyclerView = (RecyclerView)findViewById(R.id.button_tab_rv);
            btnRecyclerViewAdapter = new BtnRecyclerViewAdapter(this, list) {
                @Override
                protected void onItemFocus(View itemView, int position) {
                    itemView.setSelected(true);
                    //View view = itemView.
                }
    
                @Override
                protected void onItemGetNormal(View itemView) {
                       itemView.setSelected(false);
                }
            };
    
            FocusLinearLayoutManager linearLayoutManager1 = new FocusLinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false);
    
            btnRecyclerView.setLayoutManager(linearLayoutManager1);
            btnRecyclerView.setAdapter(btnRecyclerViewAdapter);
    
    
    
    
        }
    
    
    
    
    
    
    
        private void initView() {
            recyclerView = findViewById(R.id.rv_tan);
            imageView= findViewById(R.id.main_img);
    
    
            imageView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
                @Override
                public void onFocusChange(View view, boolean b) {
                    Log.v("img_focus",""+view.getId());
                }
            });
    
        }
    
        private void initAdapter() {
            adapter = new MyRecyclerViewAdapter(this, titles);
            LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false);
            recyclerView.setLayoutManager(linearLayoutManager);
            recyclerView.setAdapter(adapter);
            recyclerView.requestFocus();
            adapter.setmOnItemClickListener(this);
            adapter.setmOnItemClickListener(this);
        }
    
        @Override
        public void onItemClick(View view, int position) {
            Log.i("Activity:onItemClick","mOnItemFocusChangeListener.onItemFocusChange(v, position, hasFocus);");
        }
    
        @Override
        public void onItemFocusChange(View view, int position, boolean hasFocus) {
    
    
    
        }
    
    
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
    
            
    
    
            return super.onKeyDown(keyCode, event);
        }
    
        @Override
        public boolean dispatchKeyEvent(KeyEvent event) {
            //View v =  getCurrentFocus();
    
    
    
    
            return super.dispatchKeyEvent(event);
    
    
    
        }
    }

    adapter代码:

    其余的adapter基本和这个差不多

    package com.example.focusdome.adapter;
    
    import android.content.Context;
    import android.os.Build;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.core.view.ViewCompat;
    import androidx.recyclerview.widget.LinearLayoutManager;
    import androidx.recyclerview.widget.RecyclerView;
    
    import com.example.focusdome.R;
    import com.example.focusdome.activity.TabActivity;
    import com.example.focusdome.model.RecyclerMainModel;
    
    import java.util.ArrayList;
    
    public abstract class BtnRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    
        private Context context;
    
        private ArrayList<RecyclerMainModel> data;
    
        private MyRecyclerViewAdapter.OnItemFocusChangeListener mOnItemFocusChangeListener;
    
        private MyRecyclerViewAdapter.OnItemClickListener mOnItemClickListener;
    
        private final LayoutInflater layoutInflater;
        private int defaultFocus = 0;
        private boolean needFocus = true;
    
    
        public BtnRecyclerViewAdapter(Context context, ArrayList<RecyclerMainModel> list) {
            this.context = context;
            this.data = list;
            layoutInflater = LayoutInflater.from(context);
        }
    
        public interface OnItemClickListener{
            void onItemClick(View view, int position);
    
        }
    
    
        public interface OnItemFocusChangeListener{
            void onItemFocusChange(View view, int position, boolean hasFocus);
    
        }
    
        public final void setmOnItemClickListener(@Nullable MyRecyclerViewAdapter.OnItemClickListener listener){
            mOnItemClickListener = listener;
        }
    
        private void setmOnItemFocusChangeListener(@Nullable MyRecyclerViewAdapter.OnItemFocusChangeListener focusChangeListener){
            this.mOnItemFocusChangeListener = focusChangeListener;
        }
    
    
    
        @NonNull
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View v = layoutInflater.inflate(R.layout.layout_found_h_recycler_item,parent,false);
    
    
            return  new RecyclerViewHolder(v);
        }
    
        @Override
        public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder,final int position) {
            RecyclerViewHolder viewHolder = (RecyclerViewHolder)holder;
    
            viewHolder.imageView.setImageResource(data.get(position).getM_imgId());
            viewHolder.textView.setText(data.get(position).getM_txt());
    
            if (mOnItemClickListener != null) {
                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        mOnItemClickListener.onItemClick(v, position);
                        Log.e("click事件:","你点击了"+v.getId());
                    }
                });
            }
    
    
                holder.itemView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
                    @Override
                    public void onFocusChange(View v, boolean hasFocus) {
                      if (hasFocus){
                          focusStatus(v,position);
    
    
                      }else {
    
                          normalStatus(v);
    
                      }
    
                        Log.i("adapter:","onFocusChange");
                    }
                });
    
    
    
    
            if (needFocus) {
                Log.i("进行移动:",":");
    
                if (defaultFocus < 0) {
    
                    defaultFocus = 0;
                }
                if (defaultFocus >= getItemCount()) {
                    defaultFocus = getItemCount() - 1;
                }
                if (defaultFocus == position) {
                    if (!holder.itemView.isFocusable()) {
                        defaultFocus++;
                    } else {
                        holder.itemView.requestFocus();
                    }
                }
            } else {
                //setNeedFocus(position == (getItemCount() - 1));
            }
    
        }
    
        @Override
        public int getItemCount() {
            return data.size();
        }
    
    
    
    
    
        private class RecyclerViewHolder extends RecyclerView.ViewHolder {
    
            public TextView textView;
    
            public ImageView imageView;
    
    
            public RecyclerViewHolder(@NonNull View itemView) {
                super(itemView);
    
                textView = (TextView) itemView.findViewById(R.id.f_h_c_txt);
    
                imageView = (ImageView)itemView.findViewById(R.id.f_h_c_img);
    
    
            }
        }
    
        /**
         * item获得焦点时调用
         *
         * @param itemView view
         */
        private void focusStatus(View itemView,int position) {
            if (itemView == null) {
                return;
            }
    
    
            float scalX,scalY;
            scalX = 1.1f;
            scalY = 1.1f;
            if (Build.VERSION.SDK_INT >= 21) {
                //抬高Z轴
                ViewCompat.animate(itemView).scaleX(scalX).scaleY(scalY).translationZ(1.3f).start();
            } else {
                ViewCompat.animate(itemView).scaleX(scalX).scaleY(scalY).start();
                ViewGroup parent = (ViewGroup) itemView.getParent();
                parent.requestLayout();
                parent.invalidate();
            }
            onItemFocus(itemView,position);
        }
    
        /**
         * 当item获得焦点时处理
         *
         * @param itemView itemView
         */
        protected abstract void onItemFocus(View itemView,int position);
    
        /**
         * item失去焦点时
         *
         * @param itemView item对应的View
         */
        private void normalStatus(View itemView) {
            if (itemView == null) {
                return;
            }
            if (Build.VERSION.SDK_INT >= 21) {
                ViewCompat.animate(itemView).scaleX(1.0f).scaleY(1.0f).translationZ(0).start();
            } else {
                ViewCompat.animate(itemView).scaleX(1.0f).scaleY(1.0f).start();
                ViewGroup parent = (ViewGroup) itemView.getParent();
                parent.requestLayout();
                parent.invalidate();
            }
            onItemGetNormal(itemView);
        }
    
        /**
         * 当条目失去焦点时调用
         *
         * @param itemView 条目对应的View
         */
        protected abstract void onItemGetNormal(View itemView);
    
    
    }

    model代码:

    package com.example.focusdome.model;
    
    public class RecyclerMainModel {
        private String m_txt;
        private int m_imgId;
    
        public RecyclerMainModel(String m_txt, int m_imgId) {
            this.m_txt = m_txt;
            this.m_imgId = m_imgId;
        }
    
        public String getM_txt() {
            return m_txt;
        }
    
        public void setM_txt(String m_txt) {
            this.m_txt = m_txt;
        }
    
        public int getM_imgId() {
            return m_imgId;
        }
    
        public void setM_imgId(int m_imgId) {
            this.m_imgId = m_imgId;
        }
    }

    view代码:

    CircleImageView.java:

    自定义圆形ImageView

    package com.example.focusdome.view;
    
    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapShader;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Matrix;
    import android.graphics.Paint;
    import android.graphics.PorterDuff;
    import android.graphics.PorterDuffXfermode;
    import android.graphics.Rect;
    import android.graphics.Shader;
    import android.graphics.drawable.BitmapDrawable;
    import android.graphics.drawable.Drawable;
    import android.os.Build;
    import android.util.AttributeSet;
    import android.view.View;
    import android.widget.ImageView;
    
    import androidx.annotation.Nullable;
    import androidx.annotation.RequiresApi;
    
    @SuppressLint("AppCompatCustomView")
    public class CircleImageView extends ImageView { //画笔
        private Paint mPaint;
        //圆形图片的半径
        private int mRadius;
        //图片的宿放比例
        private float mScale;
    
        public CircleImageView(Context context) {
            super(context);
        }
    
        public CircleImageView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
        }
    
        public CircleImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            //由于是圆形,宽高应保持一致
            int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
            mRadius = size / 2;
            setMeasuredDimension(size, size);
        }
    
        @SuppressLint("DrawAllocation")
        @Override
        protected void onDraw(Canvas canvas) {
    
            mPaint = new Paint();
            mPaint.setColor(Color.WHITE);
    
            Drawable drawable = getDrawable();
    
            if (null != drawable) {
                Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
    
                //初始化BitmapShader,传入bitmap对象
                BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
                //计算缩放比例
                mScale = (mRadius * 2.0f) / Math.min(bitmap.getHeight(), bitmap.getWidth());
    
                Matrix matrix = new Matrix();
                matrix.setScale(mScale, mScale);
                bitmapShader.setLocalMatrix(matrix);
                mPaint.setShader(bitmapShader);
                //画圆形,指定好坐标,半径,画笔
                canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
            } else {
                super.onDraw(canvas);
            }
        }
    
    
    
    
    
    }

    自定义RecyclerView,重写dispatchKeyEvent()方法,进行焦点控制:

    FocusRecyclerView:

    package com.example.focusdome.view;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.FocusFinder;
    import android.view.KeyEvent;
    import android.view.View;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.recyclerview.widget.RecyclerView;
    
    public class FocusRecyclerView extends RecyclerView {
        public FocusRecyclerView(@NonNull Context context) {
            super(context);
        }
    
        public FocusRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
        }
    
        public FocusRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
    
        @Override
        public boolean dispatchKeyEvent(KeyEvent event) {
            if (event.getAction() == KeyEvent.ACTION_DOWN) {
                int keyCode = event.getKeyCode();
    
                //水平垂直的时候:按下左键或者右键
                if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT /*|| keyCode == KeyEvent.KEYCODE_DPAD_DOWN || keyCode == KeyEvent.KEYCODE_DPAD_UP*/) {
    
                    //获取当前焦点的视图
                    View focusedView = getFocusedChild();
                    View nextFocusView;
                    try {
    
                       /* switch (keyCode){
                            case KeyEvent.KEYCODE_DPAD_LEFT:
                                Log.v("left","往左");
                                //通过findNextFocus获取下一个需要的焦点的vie
                                nextFocusView = FocusFinder.getInstance().findNextFocus(this,focusedView,View.FOCUS_LEFT);
                                break;
    
                            case KeyEvent.KEYCODE_DPAD_RIGHT:
                                Log.v("right","往右");
                                nextFocusView = FocusFinder.getInstance().findNextFocus(this,focusedView,View.FOCUS_RIGHT);
                                break;
    
                            case KeyEvent.KEYCODE_DPAD_UP:
                                Log.v("up","往上");
                                nextFocusView = FocusFinder.getInstance().findNextFocus(this,focusedView,View.FOCUS_UP);
                                break;
    
                            case KeyEvent.KEYCODE_DPAD_DOWN:
                                nextFocusView = FocusFinder.getInstance().findNextFocus(this,focusedView,View.FOCUS_DOWN);
    
                                Log.v("down","往下");
                                break;
                            default:
                                nextFocusView = null;
                                break;
    
    
                        }*/
    
    
                        if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
    
                            Log.v("left", "焦点往左跑");
                            //通过findNextFocus获取下一个需要得到的焦点的view
                            nextFocusView = FocusFinder.getInstance().findNextFocus(this, focusedView, View.FOCUS_LEFT);
                            if(nextFocusView == null){
                                Log.v("同级","View查找");
                              //  nextFocusView = FocusFinder.getInstance().findNextFocus(this,focusedView.getRootView().,View.FOCUS_LEFT);
                                 nextFocusView = focusedView.getParent().focusSearch(focusedView,View.FOCUS_LEFT);
    
                            }
    
                        } else {
                            Log.v("right", "右边跑");
                            //通过findNextFocus获取下一个需要得到的焦点的View
                            nextFocusView = FocusFinder.getInstance().findNextFocus(this, focusedView, View.FOCUS_RIGHT);
                        }
    
    
                    } catch (Exception e) {
    
                        nextFocusView = null;
                    }
                    //如果获取失败,消耗掉事件,不让系统处理,并让原先的view获取焦点
                    if (nextFocusView == null) {
    
    
                        focusedView.requestFocus();
                        return true;
                    }
    
                }
    
    
            }
    
    
            return super.dispatchKeyEvent(event);
        }
    
    
        @Override
        public View focusSearch(int direction) {
    
    
            return super.focusSearch(direction);
        }
    }

    SpaceDecoration.java

    package com.example.focusdome.view;
    
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Rect;
    import android.graphics.drawable.ColorDrawable;
    import android.view.View;
    
    import androidx.recyclerview.widget.GridLayoutManager;
    import androidx.recyclerview.widget.LinearLayoutManager;
    import androidx.recyclerview.widget.OrientationHelper;
    import androidx.recyclerview.widget.RecyclerView;
    import androidx.recyclerview.widget.StaggeredGridLayoutManager;
    
    import com.chad.library.adapter.base.BaseQuickAdapter;
    
    import static android.widget.LinearLayout.VERTICAL;
    
    public class SpaceDecoration extends RecyclerView.ItemDecoration {
    
        private int space;
        private int headerCount = -1;
        private int footerCount = Integer.MAX_VALUE;
        private boolean mPaddingEdgeSide = true;
        private boolean mPaddingStart = true;
        private boolean mPaddingHeaderFooter = false;
        private ColorDrawable mColorDrawable;
    
        private boolean mDrawLastItem = true;
        private boolean mDrawHeaderFooter = false;
    
    
        public SpaceDecoration(int space) {
            this.mColorDrawable = new ColorDrawable(Color.parseColor("#e7e7e7"));
            this.space = space;
        }
    
        public SpaceDecoration(int space, int color) {
            this.mColorDrawable = new ColorDrawable(color);
            this.space = space;
        }
    
        public void setPaddingEdgeSide(boolean mPaddingEdgeSide) {
            this.mPaddingEdgeSide = mPaddingEdgeSide;
        }
    
        public void setPaddingStart(boolean mPaddingStart) {
            this.mPaddingStart = mPaddingStart;
        }
    
        public void setPaddingHeaderFooter(boolean mPaddingHeaderFooter) {
            this.mPaddingHeaderFooter = mPaddingHeaderFooter;
        }
    
        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            int position = parent.getChildAdapterPosition(view);
            int spanCount = 0;
            int orientation = 0;
            int spanIndex = 0;
            int headerCount = 0, footerCount = 0;
            if (parent.getAdapter() instanceof BaseQuickAdapter) {
                headerCount = ((BaseQuickAdapter) parent.getAdapter()).getHeaderLayoutCount();
                footerCount = ((BaseQuickAdapter) parent.getAdapter()).getFooterLayoutCount();
            }
    
            RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
            if (layoutManager instanceof StaggeredGridLayoutManager) {
                orientation = ((StaggeredGridLayoutManager) layoutManager).getOrientation();
                spanCount = ((StaggeredGridLayoutManager) layoutManager).getSpanCount();
                spanIndex = ((StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanIndex();
            } else if (layoutManager instanceof GridLayoutManager) {
                orientation = ((GridLayoutManager) layoutManager).getOrientation();
                spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
                spanIndex = ((GridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanIndex();
            } else if (layoutManager instanceof LinearLayoutManager) {
                orientation = ((LinearLayoutManager) layoutManager).getOrientation();
                spanCount = 1;
                spanIndex = 0;
            }
    
            /**
             * 普通Item的尺寸
             */
            if ((position >= headerCount && position < parent.getAdapter().getItemCount() - footerCount)) {
    
                if (orientation == VERTICAL) {
                    float expectedWidth = (float) (parent.getWidth() - space * (spanCount + (mPaddingEdgeSide ? 1 : -1))) / spanCount;
                    float originWidth = (float) parent.getWidth() / spanCount;
                    float expectedX = (mPaddingEdgeSide ? space : 0) + (expectedWidth + space) * spanIndex;
                    float originX = originWidth * spanIndex;
                    outRect.left = (int) (expectedX - originX);
                    outRect.right = (int) (originWidth - outRect.left - expectedWidth);
                    if (position - headerCount < spanCount && mPaddingStart) {
                        outRect.top = space;
                    }
                    outRect.bottom = space;
                    return;
                } else {
                    float expectedHeight = (float) (parent.getHeight() - space * (spanCount + (mPaddingEdgeSide ? 1 : -1))) / spanCount;
                    float originHeight = (float) parent.getHeight() / spanCount;
                    float expectedY = (mPaddingEdgeSide ? space : 0) + (expectedHeight + space) * spanIndex;
                    float originY = originHeight * spanIndex;
                    outRect.bottom = (int) (expectedY - originY);
                    outRect.top = (int) (originHeight - outRect.bottom - expectedHeight);
                    if (position - headerCount < spanCount && mPaddingStart) {
                        outRect.left = space;
                    }
                    outRect.right = space;
                    return;
                }
            } else if (mPaddingHeaderFooter) {
                if (orientation == VERTICAL) {
                    outRect.right = outRect.left = mPaddingEdgeSide ? space : 0;
                    outRect.top = mPaddingStart ? space : 0;
                } else {
                    outRect.top = outRect.bottom = mPaddingEdgeSide ? space : 0;
                    outRect.left = mPaddingStart ? space : 0;
                }
            }
    
        }
    
        @Override
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
    
            if (parent.getAdapter() == null) {
                return;
            }
    
            int orientation = 0;
            int headerCount = 0, footerCount = 0, dataCount;
    
            if (parent.getAdapter() instanceof BaseQuickAdapter) {
                headerCount = ((BaseQuickAdapter) parent.getAdapter()).getHeaderLayoutCount();
                footerCount = ((BaseQuickAdapter) parent.getAdapter()).getFooterLayoutCount();
                dataCount = parent.getAdapter().getItemCount();
            } else {
                dataCount = parent.getAdapter().getItemCount();
            }
            int dataStartPosition = headerCount;
            int dataEndPosition = headerCount + dataCount;
    
    
            RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
            if (layoutManager instanceof StaggeredGridLayoutManager) {
                orientation = ((StaggeredGridLayoutManager) layoutManager).getOrientation();
            } else if (layoutManager instanceof GridLayoutManager) {
                orientation = ((GridLayoutManager) layoutManager).getOrientation();
            } else if (layoutManager instanceof LinearLayoutManager) {
                orientation = ((LinearLayoutManager) layoutManager).getOrientation();
            }
            int start, end;
            if (orientation == OrientationHelper.VERTICAL) {
                start = parent.getPaddingLeft();
                end = parent.getWidth() - parent.getPaddingRight();
            } else {
                start = parent.getPaddingTop();
                end = parent.getHeight() - parent.getPaddingBottom();
            }
    
            int childCount = parent.getChildCount();
            for (int i = 0; i < childCount; i++) {
                View child = parent.getChildAt(i);
                int position = parent.getChildAdapterPosition(child);
    
                if (position >= dataStartPosition && position < dataEndPosition - 1//数据项除了最后一项
                        || (position == dataEndPosition - 1 && mDrawLastItem)//数据项最后一项
                        || (!(position >= dataStartPosition && position < dataEndPosition) && mDrawHeaderFooter)//header&footer且可绘制
                        ) {
    
                    if (orientation == OrientationHelper.VERTICAL) {
                        RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
                        int top = child.getBottom() + params.bottomMargin;
                        int bottom = top;
                        mColorDrawable.setBounds(start, top, end, bottom);
                        mColorDrawable.draw(c);
                    } else {
                        RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
                        int left = child.getRight() + params.rightMargin;
                        int right = left;
                        mColorDrawable.setBounds(left, start, right, end);
                        mColorDrawable.draw(c);
                    }
                }
            }
        }
    }

    防止按键速度过快RecyclerView焦点乱飞问题:

    FocusLinearLayoutManager.java

    package com.example.focusdome.view;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.View;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.recyclerview.widget.LinearLayoutManager;
    
    public class FocusLinearLayoutManager extends LinearLayoutManager {
        public FocusLinearLayoutManager(Context context) {
            super(context);
        }
    
        public FocusLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
            super(context, orientation, reverseLayout);
        }
    
        public FocusLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
        }
    
    
        @Nullable
        @Override
        public View onInterceptFocusSearch(@NonNull View focused, int direction) {
    
            Log.v("manger","ssssss");
    
            int currentPosition = getPosition(getFocusedChild());
            int count = getItemCount();
            int lastVisiblePosition = findLastVisibleItemPosition();
    
            switch (direction){
                case View.FOCUS_RIGHT:
                    currentPosition++;
                    break;
                case View.FOCUS_LEFT:
                    currentPosition++;
                    break;
                case View.FOCUS_DOWN:
                    currentPosition++;
                    break;
                case View.FOCUS_UP:
                    currentPosition++;
                    break;
    
            }
    
            if (currentPosition<0||currentPosition>count){
                return focused;
            }else {
                if (currentPosition>lastVisiblePosition){
                    scrollToPosition(currentPosition);
                }
    
            }
    
    
    
            return super.onInterceptFocusSearch(focused, direction);
        }
    }

     项目地址:https://download.csdn.net/download/qq_41861266/12691503

  • 相关阅读:
    mysql 安装
    flying-saucer-pdf使用中字符串过长换行出问题的解决办法
    杂想
    关于MATLAB实验结果求交点问题
    关于学习方向问题
    关于读取文件夹中的图片问题
    关于ROC曲线的碎碎念
    win7(64)+vs2013+opencv3.0配置的辛酸路程
    验证模式和辨识模式
    指纹识别认证
  • 原文地址:https://www.cnblogs.com/123-sxs/p/13445254.html
Copyright © 2011-2022 走看看