1、KeyUtils
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.util.Log;
import android.view.View;
import android.view.animation.ScaleAnimation;
import androidx.recyclerview.widget.RecyclerView;
import com.pjx.core.event.callback.CallbackManager;
import com.pjx.core.event.callback.IGlobalCallback;
import rxhttp.wrapper.utils.LogUtil;
public class KeyUtils {
public static void keyListenerBackground(final View mView){
mView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (b) {
mView.setSelected(true);
ScaleAnimation animationTwoCopy = new ScaleAnimation(1f, 1.1f, 1f, 1.1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwoCopy.setDuration(300);
animationTwoCopy.setFillAfter(true);
mView.startAnimation(animationTwoCopy);
}else {
mView.setSelected(false);
ScaleAnimation animationTwo = new ScaleAnimation(1.1f, 1f, 1.1f, 1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwo.setDuration(300);
animationTwo.setFillAfter(true);
mView.startAnimation(animationTwo);
}
}
});
}
public static void keyListenerBackground(final View mView, final View v2){
mView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (b) {
v2.setSelected(true);
ScaleAnimation animationTwoCopy = new ScaleAnimation(1f, 1.1f, 1f, 1.1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwoCopy.setDuration(300);
animationTwoCopy.setFillAfter(true);
mView.startAnimation(animationTwoCopy);
}else {
v2.setSelected(false);
ScaleAnimation animationTwo = new ScaleAnimation(1.1f, 1f, 1.1f, 1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwo.setDuration(300);
animationTwo.setFillAfter(true);
mView.startAnimation(animationTwo);
}
}
});
}
public static void keyListenerBackground(final View mView, final int position, final String type){
mView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (b) {
IGlobalCallback callback= CallbackManager.Companion.getInstance().getCallback(type);
if (callback != null) {
callback.executeCallback(position);
}
mView.setSelected(true);
ScaleAnimation animationTwoCopy = new ScaleAnimation(1f, 1.1f, 1f, 1.1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwoCopy.setDuration(300);
animationTwoCopy.setFillAfter(true);
mView.startAnimation(animationTwoCopy);
}else {
mView.setSelected(false);
ScaleAnimation animationTwo = new ScaleAnimation(1.1f, 1f, 1.1f, 1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwo.setDuration(300);
animationTwo.setFillAfter(true);
mView.startAnimation(animationTwo);
}
}
});
}
/*****************************item获得与失去焦点的监听***************************/
public static void keyListenerItem(final View mView){
mView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (b) {
mView.setSelected(true);
ScaleAnimation animationTwoCopy = new ScaleAnimation(1f, 1.02f, 1f, 1.02f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwoCopy.setDuration(300);
animationTwoCopy.setFillAfter(true);
mView.startAnimation(animationTwoCopy);
yesBorder(mView);
}else {
mView.setSelected(false);
//mView.setBackgroundResource(R.drawable.shape_select_background_false);
ScaleAnimation animationTwo = new ScaleAnimation(1.02f, 1f, 1.02f, 1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwo.setDuration(300);
animationTwo.setFillAfter(true);
mView.startAnimation(animationTwo);
noBorder(mView);
}
}
});
}
public static void keyListenerItem(final View mView,RecyclerView rv){
mView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
LogUtil.log("选择"+b);
LogUtil.log("view="+view);
if (b) {
mView.setSelected(true);
ScaleAnimation animationTwoCopy = new ScaleAnimation(1f, 1.02f, 1f, 1.02f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwoCopy.setDuration(300);
animationTwoCopy.setFillAfter(true);
mView.startAnimation(animationTwoCopy);
rv.smoothScrollToPosition(rv.getChildLayoutPosition(view));
yesBorder(mView);
}else {
mView.setSelected(false);
//mView.setBackgroundResource(R.drawable.shape_select_background_false);
ScaleAnimation animationTwo = new ScaleAnimation(1.02f, 1f, 1.02f, 1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwo.setDuration(300);
animationTwo.setFillAfter(true);
mView.startAnimation(animationTwo);
noBorder(mView);
}
}
});
}
public static void keyListenerItem(final View mView, final int position, final String type){
mView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (b) {
IGlobalCallback callback=CallbackManager.Companion.getInstance().getCallback(type);
if (callback != null) {
callback.executeCallback(position);
}
ScaleAnimation animationTwoCopy = new ScaleAnimation(1f, 1.06f, 1f, 1.06f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwoCopy.setDuration(300);
animationTwoCopy.setFillAfter(true);
mView.startAnimation(animationTwoCopy);
yesBorder(mView);
}else {
ScaleAnimation animationTwo = new ScaleAnimation(1.06f, 1f, 1.06f, 1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwo.setDuration(300);
animationTwo.setFillAfter(true);
mView.startAnimation(animationTwo);
noBorder(mView);
}
}
});
}
/********************************************************/
public static void keyListenerText(final View mView){
mView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (b) {
ScaleAnimation animationTwoCopy = new ScaleAnimation(1f, 1.15f, 1f, 1.15f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwoCopy.setDuration(300);
animationTwoCopy.setFillAfter(true);
mView.startAnimation(animationTwoCopy);
yesBorder(mView);
}else {
ScaleAnimation animationTwo = new ScaleAnimation(1.15f, 1f, 1.15f, 1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwo.setDuration(300);
animationTwo.setFillAfter(true);
mView.startAnimation(animationTwo);
noBorder(mView);
}
}
});
}
private static void yesBorder(View mView){
//创建Drawable对象
GradientDrawable drawable=new GradientDrawable();
drawable.setStroke(3, Color.parseColor("#A4D9DF"));
drawable.setColor(Color.TRANSPARENT);
drawable.setCornerRadius(6);
mView.setBackground(drawable);
}
private static void noBorder(View mView){
GradientDrawable drawable=new GradientDrawable();
drawable.setCornerRadius(6);
drawable.setColor(Color.TRANSPARENT);
mView.setBackground(drawable);
}
}
2、AnimationUtil
import android.animation.Animator;
import android.animation.Keyframe;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.widget.ImageView;
public class AnimationUtil {
private AnimationUtil() {
}
private static final String TAG = AnimationUtil.class.getSimpleName();
public static void zoomByFactor(View view, float factor, int duration) {
ScaleAnimation animation = AnimationBuilder.getInstance()
.getScaleAnimation(1.0f, factor, 1.0f, factor,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f, duration);
if (animation != null) {
view.startAnimation(animation);
}
}
public static void scaleToOriginalDimension(View view, float factor, int duration) {
ScaleAnimation animation = AnimationBuilder.getInstance()
.getScaleAnimation(factor, 1.0f, factor, 1.0f,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f, duration);
if (animation != null) {
view.startAnimation(animation);
}
}
//键盘移动的位移动画,动画类型为属性动画
public static void slideView(View view, final float p1, final float p2, int duration, final View showView, final View hideView) {
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, "translationX", p1, p2);
objectAnimator.setDuration(duration);
objectAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
// try {
//
// } catch (Exception e) {
// Log.e(TAG, "wqs:slideView:onAnimationStart:Exception:" + e.toString());
// e.printStackTrace();
// }
}
@Override
public void onAnimationEnd(Animator animator) {
// if (showView != null) {
// showView.setVisibility(View.VISIBLE);
// }
// if (hideView != null) {
// hideView.setVisibility(View.INVISIBLE);
// }
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
objectAnimator.start();
}
public static void doBoundaryAnimation(View view, int keyCode, int ratio) {
int leftShakeDegrees = 6 * ratio;
int rightShakeDegrees = 2 * ratio;
if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
leftShakeDegrees = 2 * ratio;
rightShakeDegrees = 6 * ratio;
}
PropertyValuesHolder rotateValuesHolder = PropertyValuesHolder.ofKeyframe(View.TRANSLATION_X,
Keyframe.ofFloat(0f, 0f),
Keyframe.ofFloat(0.2f, -leftShakeDegrees),
Keyframe.ofFloat(0.4f, rightShakeDegrees),
Keyframe.ofFloat(0.6f, -leftShakeDegrees),
Keyframe.ofFloat(0.8f, rightShakeDegrees),
Keyframe.ofFloat(1.0f, 0f)
);
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(view, rotateValuesHolder);
objectAnimator.setDuration(500);
objectAnimator.start();
}
public static void startLoadingAni(ImageView loadingImg) {
if (loadingImg == null) {
Log.e(TAG, "wqs:startLoadingAni:loadingImg==null");
return;
}
loadingImg.clearAnimation();
RotateAnimation rotateAnimation = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setFillAfter(true);
rotateAnimation.setRepeatMode(Animation.RESTART);
rotateAnimation.setRepeatCount(Animation.INFINITE);
rotateAnimation.setDuration(1000);
rotateAnimation.setInterpolator(new LinearInterpolator());
loadingImg.startAnimation(rotateAnimation);
showView(loadingImg);
}
public static void stopLoadingAni(ImageView loadingImg) {
if (loadingImg == null) {
Log.e(TAG, "wqs:stopLoadingAni:loadingImg==null");
return;
}
loadingImg.clearAnimation();
goneView(loadingImg);
}
public static void showView(View view) {
if (view != null) {
view.setVisibility(View.VISIBLE);
}
}
public static void hideView(View view) {
if (view != null) {
view.setVisibility(View.INVISIBLE);
}
}
public static void goneView(View view) {
if (view != null) {
view.setVisibility(View.GONE);
}
}
public static void setFouseView(View view) {
if (view != null) {
view.requestFocus();
}
}
}
3、AnimationBuilder
import android.view.animation.ScaleAnimation;
public final class AnimationBuilder {
private static AnimationBuilder mInstance;
private AnimationBuilder() {
}
public static synchronized AnimationBuilder getInstance() {
if (mInstance == null) {
mInstance = new AnimationBuilder();
}
return mInstance;
}
public ScaleAnimation getScaleAnimation(float fromX, float toX,
float fromY, float toY, int pivotXType, float pivotXValue,
int pivotYType, float pivotYValue, int duration) {
ScaleAnimation sa = new ScaleAnimation(fromX, toX, fromY, toY,
pivotXType, pivotXValue,
pivotYType, pivotYValue);
sa.setDuration(duration);
sa.setFillAfter(true);
return sa;
}
}
4、IRecyclerView
import android.view.View;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
/**
* @author weihaichao
* @date 2019-10-10 16:00
*/
public interface IRecyclerView {
int ALIGN_MODE_START = 2;
int ALIGN_MODE_CENTER = 1;
int ALIGN_MODE_FIRST = 3;
int DIRECTION_HORIZONTAL = LinearLayoutManager.HORIZONTAL;
int DIRECTION_VERTICAL = LinearLayoutManager.VERTICAL;
/**
* 获取默认焦点View
* @return View
*/
@Nullable
View getDefaultFocusView();
/**
* 请求默认焦点
* @return Boolean 是否请求成功
*/
boolean requestDefaultFocus();
/**
* 设置对齐方式
* @param mode 对齐方式
* @param direction
*/
void setLayoutManager(int mode, int direction);
}
5、CenterLayoutManager (居中移动)
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.LinearSmoothScroller;
import androidx.recyclerview.widget.RecyclerView;
public class CenterLayoutManager extends LinearLayoutManager {
public CenterLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
RecyclerView.SmoothScroller centerSmoothScroller = new CenterSmoothScroller(recyclerView.getContext());
centerSmoothScroller.setTargetPosition(position);
startSmoothScroll(centerSmoothScroller);
}
@Override
protected int getExtraLayoutSpace(RecyclerView.State state) {
return 100;
}
@Nullable
@Override
public View onInterceptFocusSearch(@NonNull View focused, int direction) {
int pos = getPosition(focused);
if (pos != findLastCompletelyVisibleItemPosition()) {
return null;
}
return super.onInterceptFocusSearch(focused, direction);
}
private static class CenterSmoothScroller extends LinearSmoothScroller {
CenterSmoothScroller(Context context) {
super(context);
}
@Override
public int calculateDxToMakeVisible(View view, int snapPreference) {
final RecyclerView.LayoutManager layoutManager = getLayoutManager();
if (layoutManager == null || !layoutManager.canScrollHorizontally()) {
return 0;
}
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
view.getLayoutParams();
final int left = view.getLeft() - params.leftMargin;
final int right = view.getRight() + params.rightMargin;
final int start = layoutManager.getPaddingLeft();
final int end = layoutManager.getWidth() - layoutManager.getPaddingRight();
return (start + (end - start) / 2) - (left + (right - left) / 2);
}
@Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return 60f / displayMetrics.densityDpi;
}
}
}
6、BothSidesLayoutManager(两边移动)
import android.content.Context;
import android.util.DisplayMetrics;
import android.util.Log;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.LinearSmoothScroller;
import androidx.recyclerview.widget.RecyclerView;
public class BothSidesLayoutManager extends LinearLayoutManager {
public BothSidesLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
int position) {
RecyclerView.SmoothScroller smoothScroller =
new StartSmoothScroller(recyclerView.getContext());
smoothScroller.setTargetPosition(position);
startSmoothScroll(smoothScroller);
}
private static class StartSmoothScroller extends LinearSmoothScroller {
StartSmoothScroller(Context context) {
super(context);
}
@Override
public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd,
int snapPreference) {
Log.d("LayoutManager","vs="+viewStart+" vd="+viewEnd+" bs="+boxStart+" bd="+boxEnd);
return boxStart - viewStart;
}
@Override
protected int getHorizontalSnapPreference() {
return SNAP_TO_START;
}
@Override
protected int getVerticalSnapPreference() {
return SNAP_TO_START;
}
@Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return 80f / displayMetrics.densityDpi;
}
}
}
7、FirstLayoutManager(首个移动)
mport android.content.Context;
import android.util.DisplayMetrics;
import android.util.Log;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.LinearSmoothScroller;
import androidx.recyclerview.widget.RecyclerView;
public class FirstLayoutManager extends LinearLayoutManager {
public FirstLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
int position) {
RecyclerView.SmoothScroller smoothScroller =
new FirstSmoothScroller(recyclerView.getContext());
smoothScroller.setTargetPosition(position);
startSmoothScroll(smoothScroller);
}
private static class FirstSmoothScroller extends LinearSmoothScroller {
FirstSmoothScroller(Context context) {
super(context);
}
@Override
public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd,
int snapPreference) {
Log.d("LayoutManager","vs="+viewStart+" vd="+viewEnd+" bs="+boxStart+" bd="+boxEnd);
return boxStart - viewStart + (viewEnd - viewStart);
}
@Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return 150f / displayMetrics.densityDpi;
}
}
}
下面的方式有缺陷
1、CenterFocusLinearLayoutManager 类是解决LinearLayoutManager模式下的item居中问题同时也控制了焦点乱跳问题,有多个重载构造函数,其中isLeft表示是否控制左键,其他参数就不用我说了吧。如果false表示不自己控制左键,那么将默认使用系统的规范。
isLeft默认true
isRight默认true
isUp默认false
isDown默认false
public class CenterFocusLinearLayoutManager extends LinearLayoutManager {
private int orientation = VERTICAL;
public CenterFocusLinearLayoutManager(Context context) {
super(context);
}
public CenterFocusLinearLayoutManager(Context context, boolean isLeft, boolean isRight) {
super(context);
this.isLeft = isLeft;
this.isRight = isRight;
}
public CenterFocusLinearLayoutManager(Context context, boolean isLeft, boolean isRight, boolean isDown) {
super(context);
this.isLeft = isLeft;
this.isRight = isRight;
this.isDown = isDown;
}
public CenterFocusLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
this.orientation = orientation;
}
public CenterFocusLinearLayoutManager(Context context, int orientation, boolean reverseLayout, boolean isLeft, boolean isRight) {
super(context, orientation, reverseLayout);
this.isLeft = isLeft;
this.isRight = isRight;
this.orientation = orientation;
}
public CenterFocusLinearLayoutManager(Context context, int orientation, boolean reverseLayout, boolean isLeft, boolean isRight, boolean isDown) {
super(context, orientation, reverseLayout);
this.isLeft = isLeft;
this.isRight = isRight;
this.isDown = isDown;
this.orientation = orientation;
}
public CenterFocusLinearLayoutManager(Context context, int orientation, boolean reverseLayout, boolean isLeft, boolean isRight, boolean isUp, boolean isDown) {
super(context, orientation, reverseLayout);
this.isLeft = isLeft;
this.isRight = isRight;
this.isUp = isUp;
this.isDown = isDown;
this.orientation = orientation;
}
private boolean isLeft = true;
private boolean isRight = true;
private boolean isUp = false;
private boolean isDown = false;
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
RecyclerView.SmoothScroller smoothScroller = new CenterSmoothScroller(recyclerView.getContext());
smoothScroller.setTargetPosition(position);
startSmoothScroll(smoothScroller);
}
public static class CenterSmoothScroller extends LinearSmoothScroller {
CenterSmoothScroller(Context context) {
super(context);
}
@Override
public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) {
return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2);
}
}
private long mLastKeyDownTime = 0;
@Override
public View onInterceptFocusSearch(View focused, int direction) {
long current = System.currentTimeMillis();
if (current - mLastKeyDownTime < 500) {//延时获得焦点
return focused;
} else {
mLastKeyDownTime = current;
if (getFocusedChild() != null) {
int pos = getPosition(getFocusedChild());//这里要用这个方法
// int pos = getPosition(focused);//这里要用这个方法
int count = getItemCount();
int lastVisiblePosition = findLastVisibleItemPosition();
switch (direction) {
case View.FOCUS_LEFT:
if (isLeft) {
if (orientation == VERTICAL) {
return focused;
} else {
if (pos == 0) {
return focused;
}
}
}
break;
case View.FOCUS_RIGHT:
if (isRight) {
if (orientation == VERTICAL) {
return focused;
} else {
if (pos == count - 1) {
return focused;
}
}
}
break;
case View.FOCUS_UP:
if (isUp) {
if (orientation == VERTICAL) {
if (pos == 0) {
return focused;
}
} else {
return focused;
}
}
break;
case View.FOCUS_DOWN:
if (isDown) {
if (orientation == VERTICAL) {
if (pos == count - 1) {
return focused;
}
} else {
return focused;
}
}
break;
}
if (pos > getItemCount() - 1) {
return focused;
} else if (pos > lastVisiblePosition) {
scrollToPosition(pos);
}
}
return super.onInterceptFocusSearch(focused, direction);
}
}
}
如果想要居中的话需要写一个回调接口,在adapter中传position给activity,并在回调中加入下面代码即可
mRecyclerView.smoothScrollToPosition(position);
2、CenterFocusGridLayoutManager 类是解决GridLayoutManager模式下的item居中问题同时也控制了焦点乱跳问题,如果不居中,本人也想不到其他方法控制焦点乱跳,网上的方法都试过,没效果。
isLeft默认true
isRight默认true
isUp默认false
isDown默认false
isAlone默认false
public class CenterFocusGridLayoutManager extends GridLayoutManager {
private int spanCount;
private int orientation= VERTICAL;
public CenterFocusGridLayoutManager(Context context, int spanCount) {
super(context, spanCount);
this.spanCount = spanCount;
}
public CenterFocusGridLayoutManager(Context context, int spanCount, boolean isAlone) {
super(context, spanCount);
this.spanCount = spanCount;
this.isAlone = isAlone;
}
public CenterFocusGridLayoutManager(Context context, int spanCount, boolean isLeft, boolean isRight) {
super(context, spanCount);
this.spanCount = spanCount;
this.isLeft = isLeft;
this.isRight = isRight;
}
public CenterFocusGridLayoutManager(Context context, int spanCount, boolean isLeft, boolean isRight, boolean isDown) {
super(context, spanCount);
this.spanCount = spanCount;
this.isLeft = isLeft;
this.isRight = isRight;
this.isDown = isDown;
}
public CenterFocusGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout, boolean isLeft, boolean isRight) {
super(context, spanCount, orientation, reverseLayout);
this.spanCount = spanCount;
this.isLeft = isLeft;
this.isRight = isRight;
this.orientation = orientation;
}
public CenterFocusGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout,boolean isAlone, boolean isLeft, boolean isRight,boolean isUp, boolean isDown) {
super(context, spanCount, orientation, reverseLayout);
this.spanCount = spanCount;
this.orientation = orientation;
this.isAlone = isAlone;
this.isLeft = isLeft;
this.isRight = isRight;
this.isUp = isUp;
this.isDown = isDown;
}
private boolean isRight = true;
private boolean isLeft = true;
private boolean isUp=false;
private boolean isDown = false;
private boolean isAlone=false;
//用来控制自定义每行/每列不同个数的焦点,默认false。因为平常的就不适用了
private int[] rightPosArray;
private int[] leftPosArray;
public void setRightPosArray(int[] rightPosArray) {
this.rightPosArray = rightPosArray;
}
public void setLeftPosArray(int[] leftPosArray) {
this.leftPosArray = leftPosArray;
}
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
RecyclerView.SmoothScroller smoothScroller = new CenterSmoothScroller(recyclerView.getContext());
smoothScroller.setTargetPosition(position);
startSmoothScroll(smoothScroller);
}
public static class CenterSmoothScroller extends LinearSmoothScroller {
CenterSmoothScroller(Context context) {
super(context);
}
@Override
public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) {
return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2);
}
}
private long mLastKeyDownTime = 0;
@Override
public View onInterceptFocusSearch(View focused, int direction) {
long current = System.currentTimeMillis();
if (current - mLastKeyDownTime < 500) {
return focused;
} else {
mLastKeyDownTime = current;
if (getFocusedChild() != null) {
int pos = getPosition(getFocusedChild());
int lastVisibleItemPos = findLastVisibleItemPosition();
int count = getItemCount();
pos += 1;
if (direction == View.FOCUS_RIGHT) {
if (isAlone) {
for (int position : rightPosArray) {
if (pos == position) {
return focused;
}
}
} else if (isRight) {
if (orientation == VERTICAL) {
if (pos % spanCount == 0) {//|| pos==getChildCount()
return focused;
}
} else {
if (pos > count - spanCount) {
return focused;
}
}
}
} else if (direction == View.FOCUS_LEFT) {
if (isAlone) {
for (int position : leftPosArray) {
if (pos == position) {
return focused;
}
}
} else if (isLeft) {
if (orientation == VERTICAL) {
if (pos % spanCount == 1) {
return focused;
}
} else {
if (pos <= spanCount) {
return focused;
}
}
}
} else if (direction == View.FOCUS_UP) {
if (isUp) {
if (orientation == VERTICAL) {
if (pos <= spanCount) {
return focused;
}
} else {
if (pos % spanCount == 1) {
return focused;
}
}
}
} else if (direction == View.FOCUS_DOWN) {
if (isDown) {
if (orientation == VERTICAL) {
if (pos > count - spanCount) {
return focused;
}
} else {
if (pos % spanCount == 0) {
return focused;
}
}
}
}
if (pos > getItemCount()) {
return focused;
} else if (pos > lastVisibleItemPos+1) {
scrollToPosition(pos);
}
}
return super.onInterceptFocusSearch(focused, direction);
}
}
}
3、给大家一个焦点获得与失去监听的工具类(获得焦点的view会变大且可以获得边框并且可以通过回调得到选中的position)
public class KeyUtils {
public static void keyListenerBackground(final View mView){
mView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (b) {
mView.setSelected(true);
ScaleAnimation animationTwoCopy = new ScaleAnimation(1f, 1.1f, 1f, 1.1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwoCopy.setDuration(300);
animationTwoCopy.setFillAfter(true);
mView.startAnimation(animationTwoCopy);
}else {
mView.setSelected(false);
ScaleAnimation animationTwo = new ScaleAnimation(1.1f, 1f, 1.1f, 1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwo.setDuration(300);
animationTwo.setFillAfter(true);
mView.startAnimation(animationTwo);
}
}
});
}
public static void keyListenerBackground(final View mView, final View v2){
mView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (b) {
v2.setSelected(true);
ScaleAnimation animationTwoCopy = new ScaleAnimation(1f, 1.1f, 1f, 1.1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwoCopy.setDuration(300);
animationTwoCopy.setFillAfter(true);
mView.startAnimation(animationTwoCopy);
}else {
v2.setSelected(false);
ScaleAnimation animationTwo = new ScaleAnimation(1.1f, 1f, 1.1f, 1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwo.setDuration(300);
animationTwo.setFillAfter(true);
mView.startAnimation(animationTwo);
}
}
});
}
public static void keyListenerBackground(final View mView, final int position, final String type){
mView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (b) {
IGlobalCallback callback= CallbackManager.getInstance().getCallback(type);
if (callback != null) {
callback.executeCallback(position);
}
mView.setSelected(true);
ScaleAnimation animationTwoCopy = new ScaleAnimation(1f, 1.1f, 1f, 1.1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwoCopy.setDuration(300);
animationTwoCopy.setFillAfter(true);
mView.startAnimation(animationTwoCopy);
}else {
mView.setSelected(false);
ScaleAnimation animationTwo = new ScaleAnimation(1.1f, 1f, 1.1f, 1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwo.setDuration(300);
animationTwo.setFillAfter(true);
mView.startAnimation(animationTwo);
}
}
});
}
/*****************************item获得与失去焦点的监听***************************/
public static void keyListenerItem(final View mView){
mView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (b) {
mView.setSelected(true);
ScaleAnimation animationTwoCopy = new ScaleAnimation(1f, 1.02f, 1f, 1.02f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwoCopy.setDuration(300);
animationTwoCopy.setFillAfter(true);
mView.startAnimation(animationTwoCopy);
yesBorder(mView);
}else {
mView.setSelected(false);
//mView.setBackgroundResource(R.drawable.shape_select_background_false);
ScaleAnimation animationTwo = new ScaleAnimation(1.02f, 1f, 1.02f, 1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwo.setDuration(300);
animationTwo.setFillAfter(true);
mView.startAnimation(animationTwo);
noBorder(mView);
}
}
});
}
public static void keyListenerItem(final View mView, final int position, final String type){
mView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (b) {
IGlobalCallback callback=CallbackManager.getInstance().getCallback(type);
if (callback != null) {
callback.executeCallback(position);
}
ScaleAnimation animationTwoCopy = new ScaleAnimation(1f, 1.06f, 1f, 1.06f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwoCopy.setDuration(300);
animationTwoCopy.setFillAfter(true);
mView.startAnimation(animationTwoCopy);
yesBorder(mView);
}else {
ScaleAnimation animationTwo = new ScaleAnimation(1.06f, 1f, 1.06f, 1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwo.setDuration(300);
animationTwo.setFillAfter(true);
mView.startAnimation(animationTwo);
noBorder(mView);
}
}
});
}
/********************************************************/
public static void keyListenerText(final View mView){
mView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (b) {
ScaleAnimation animationTwoCopy = new ScaleAnimation(1f, 1.15f, 1f, 1.15f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwoCopy.setDuration(300);
animationTwoCopy.setFillAfter(true);
mView.startAnimation(animationTwoCopy);
yesBorder(mView);
}else {
ScaleAnimation animationTwo = new ScaleAnimation(1.15f, 1f, 1.15f, 1f, mView.getWidth() / 2, mView.getHeight() / 2);
animationTwo.setDuration(300);
animationTwo.setFillAfter(true);
mView.startAnimation(animationTwo);
noBorder(mView);
}
}
});
}
private static void yesBorder(View mView){
//创建Drawable对象
GradientDrawable drawable=new GradientDrawable();
drawable.setStroke(3, Color.parseColor("#A4D9DF"));
drawable.setColor(Color.TRANSPARENT);
drawable.setCornerRadius(6);
mView.setBackground(drawable);
}
private static void noBorder(View mView){
GradientDrawable drawable=new GradientDrawable();
drawable.setCornerRadius(6);
drawable.setColor(Color.TRANSPARENT);
mView.setBackground(drawable);
}
}