Android TV ScrollView选中子控件居中并且平滑滚动
第一次写,不会上传视频,直接上代码了
NestedScrollView
package com.gfsoftware.launcher.view;
import android.content.Context;
import android.graphics.Rect;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.widget.NestedScrollView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.FocusFinder;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import com.gfsoftware.launcher.listener.ScrollViewListener;
import com.gfsoftware.launcher.widget.SizeUtils;
/**
* 版权 (C), UT
* 作者: zyl on 2019/5/14 16:22
* 描述: ${DESCRIPTION}
* 修改人:
* 修改描述:
* 修改日期:
*/
public class ObservableScrollView extends NestedScrollView {
private final static String TAG = ObservableScrollView.class.getName();
private ScrollViewListener mScrollViewListener;
public ObservableScrollView(@NonNull Context context) {
super(context);
init();
}
public ObservableScrollView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public ObservableScrollView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setNestedScrollingEnabled(false);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (mScrollViewListener != null) {
mScrollViewListener.onScrollChanged(this, l, t, oldl, oldt);
}
}
public void setScrollViewListener(ScrollViewListener listener) {
this.mScrollViewListener = listener;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d(TAG, "onInterceptTouchEvent: ------>>");
return super.onInterceptTouchEvent(ev);
}
private View mFocusedView;
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
Log.d(TAG, "dispatchKeyEvent: ------>> action=" + event.getAction());
if (event.getAction() == KeyEvent.ACTION_DOWN) {
View nextFocused = getNextFocusView(event.getKeyCode());
if (nextFocused != null) {
mFocusedView = nextFocused;
Log.d(TAG, "dispatchKeyEvent: ------>> nextFocused=" + nextFocused);
nextFocused.requestFocus();
smoothScrollTo(this, nextFocused);
return true;
}
} else if (event.getAction() == KeyEvent.ACTION_UP) {
if (mFocusedView != null) {
mFocusedView = null;
return true;
}
}
return super.dispatchKeyEvent(event);
}
public View getNextFocusView(int keyCode) {
View currentFocused = findFocus();
Log.d(TAG, "getNextFocusView: ------>> currentFocused=" + currentFocused);
if (currentFocused != null) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_DOWN:
return FocusFinder.getInstance().findNextFocus(this,
currentFocused, View.FOCUS_DOWN);
case KeyEvent.KEYCODE_DPAD_UP:
return FocusFinder.getInstance().findNextFocus(this,
currentFocused, View.FOCUS_UP);
}
}
Log.d(TAG, "getNextFocusView: ------>> view is null....");
return null;
}
/*@Override
protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
//https://blog.csdn.net/lbcab/article/details/54311982
Log.d(TAG, "computeScrollDeltaToGetChildRectOnScreen: ------>>");
return super.computeScrollDeltaToGetChildRectOnScreen(rect);
}*/
public void smoothScrollTo(FrameLayout f, final View v) {
if (v != null) {
int min = SizeUtils.dp2px(v.getContext(), 50);
int vh = v.getHeight();
int oh = getHeight();
int[] vr = new int[2];
int[] or = new int[2];
v.getLocationOnScreen(vr);
getLocationOnScreen(or);
int tp = vr[1] - or[1];
int bp = (or[1] + oh) - (vr[1] + vh);
if (min > tp || min > bp) {
final int offset = v.getTop() - (oh - vh) / 2;
postOnAnimation(new Runnable() {
@Override
public void run() {
smoothScrollTo(0, offset);
}
});
}
}
}
}
HorizontalScrollView
package cn.cbg.yutv.layout;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.FocusFinder;
import android.view.KeyEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import cn.cbg.yutv.listener.ScrollViewListener;
import cn.cbg.yutv.utils.SizeUtils;
/**
* 版权 (C), UT
* 作者: zyl on 2019/5/14 16:22
* 描述: ${DESCRIPTION}
* 修改人:
* 修改描述:
* 修改日期:
*/
public class ObservableHorizontalScrollView extends HorizontalScrollView {
private static final String TAG = ObservableHorizontalScrollView.class.getName();
private ScrollViewListener mScrollViewListener;
private View mFocusedView;
public ObservableHorizontalScrollView(@NonNull Context context) {
super(context);
init();
}
public ObservableHorizontalScrollView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public ObservableHorizontalScrollView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (mScrollViewListener != null) {
mScrollViewListener.onScrollChanged(this, l, t, oldl, oldt);
}
}
public void setScrollViewListener(ScrollViewListener listener) {
this.mScrollViewListener = listener;
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
Log.d(TAG, "dispatchKeyEvent: ------>> action=" + event.getAction());
if (event.getAction() == KeyEvent.ACTION_DOWN) {
View nextFocused = getNextFocusView(event.getKeyCode());
if (nextFocused != null) {
mFocusedView = nextFocused;
Log.d(TAG, "dispatchKeyEvent: ------>> nextFocused=" + nextFocused);
nextFocused.requestFocus();
smoothScrollTo(this, nextFocused);
return true;
}
} else if (event.getAction() == KeyEvent.ACTION_UP) {
if (mFocusedView != null) {
mFocusedView = null;
return true;
}
}
return super.dispatchKeyEvent(event);
}
public View getNextFocusView(int keyCode) {
View currentFocused = findFocus();
Log.d(TAG, "getNextFocusView: ------>> currentFocused=" + currentFocused);
if (currentFocused != null) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT:
return FocusFinder.getInstance().findNextFocus(this,
currentFocused, View.FOCUS_LEFT);
case KeyEvent.KEYCODE_DPAD_RIGHT:
return FocusFinder.getInstance().findNextFocus(this,
currentFocused, View.FOCUS_RIGHT);
}
}
Log.d(TAG, "getNextFocusView: ------>> view is null....");
return null;
}
private void smoothScrollTo(FrameLayout f, View v) {
if (v != null) {
int min = SizeUtils.dp2px(v.getContext(), 50);
int vw = v.getWidth();
int ow = getWidth();
int[] vr = new int[2];
int[] or = new int[2];
v.getLocationOnScreen(vr);
getLocationOnScreen(or);
int tp = vr[0] - or[0];
int bp = (or[0] + ow) - (vr[0] + vw);
if (min > tp || min > bp) {
final int offset = v.getLeft() - (ow - vw) / 2;
postOnAnimation(new Runnable() {
@Override
public void run() {
smoothScrollTo(offset, 0);
}
});
}
}
}
}
参考:https://blog.csdn.net/lbcab/article/details/54311982