14

在我的 fire tv 应用程序中,我使用的是recyclerviewwith horizontal layout.

使用 dpad 滚动作品和项目正在获得关注。

但是当我按住按钮时,它滚动得非常快,因为触发了许多 keydown 事件,并且项目失去了焦点,并且无法再滚动,因为Textview我的 recyclerview 上方的另一个正在获得焦点。

它看起来像一个错误。有什么解决方法吗?

4

6 回答 6

8

我认为@tmm1 的答案是迄今为止最好的答案。如果用户使用 DPAD 滚动太快,我已经成功地实现了这个解决方法来解决 RecyclerView 中加载的元素失去焦点的问题。

在我的 RecyclerView 的适配器中,我使用 LayoutInflater 来膨胀我的元素视图,如下所示

@Override
public ListItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
    View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_keyboard_key, viewGroup, false);
    return new ListItemViewHolder(itemView);
}

我的 item_keyboard_key.xml 最初是这样定义的

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/item_keyboard_key_layout"
    android:orientation="vertical"
    android:gravity="center"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/item_keyboard_key_text"
        android:text="A"/>

</FrameLayout>

然后我创建了一个新的自定义 FrameLayout 类 (FocusFixFrameLayout) 扩展 FrameLayout 并将其用作我的根布局。我的 item_keyboard_key.xml 然后变成了

<?xml version="1.0" encoding="utf-8"?>
<no.bluebit.views.FocusFixFrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/item_keyboard_key_layout"
    android:orientation="vertical"
    android:gravity="center"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/item_keyboard_key_text"
        android:text="A"/>

</no.bluebit.views.FocusFixFrameLayout>

我的 FocusFixFrameLayout 类看起来像这样

public class FocusFixFrameLayout extends FrameLayout {

    public FocusFixFrameLayout(@NonNull Context context) {
        super(context);
    }

    public FocusFixFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public FocusFixFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public FocusFixFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
}

    @Override
    public void clearFocus() {
        if(this.getParent() != null)
            super.clearFocus();
    }
}
于 2018-06-20T20:46:39.277 回答
5

我面临同样的问题,我在我的项目中所做的就像在我的活动(包含 RecyclerView)中一样:

    private long mLastKeyDownTime = 0;
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        long current = System. currentTimeMillis();
        boolean res = false;
        if (current - mLastKeyDownTime < 300 ) {
            res = true;
        } else {
            res = super.onKeyDown(keyCode, event);
            mLastKeyDownTime = current;
        }
        return res;
    }

这避免了当您按住 dpad 上的按钮时快速滚动,并且焦点在我的 RecyclerView 中工作正常。

于 2016-03-05T02:21:32.727 回答
3

Looks like this is a bug.

See https://stackoverflow.com/a/33190656/332798 and https://issuetracker.google.com/issues/37067220


I was able to work around this bug by neutering clearFocus() on my item views, so detached views losing focus did not move focus outside the RecyclerView:

override fun clearFocus() {
    if (parent != null)
        super.clearFocus()
}
于 2018-01-10T16:50:26.037 回答
0

android 上的 RecyclerView 在使用诸如 dpad、控制器或键盘之类的 KeyListener 时存在失去焦点的错误。

我发现的解决方法是创建一个函数来禁用您在活动中拥有的所有可聚焦元素。例子:

    private void defineFocus(boolean trueOrFalse){

    ImageView downloadsSmall = (ImageView)findViewById(R.id.small_downloads_img);
    downloadsSmall.clearFocus();
    ImageView settingsSmall = (ImageView)findViewById(R.id.small_settings_img);
    settingsSmall.clearFocus();

    downloadsSmall.setFocusable(trueOrFalse);
    settingsSmall.setFocusable(trueOrFalse);

}

当我想水平或垂直滚动​​我的 recyclerview 时,我首先调用 defineFocus(false); 稍后,如果我想摆脱我的 RecyclerView/adapter,我将首先定义Focus(true); 然后请求关注按钮/图像/编辑文本/文本视图或我想要的回收器视图之外的任何内容。

于 2022-02-10T20:38:56.090 回答
0

尝试使用 notifyItemChanged(position) 这是我的工作。我在适配器内部调用了适配器,并且我的子适配器有多个edittext,当我调用notifydatasetchange 时它们会失去焦点。所以我用 notifyItemChanged(Position) 替换。

notifyItemChanged(position);
于 2021-07-19T09:21:01.157 回答
-2

在为Android TVleanback library开发项目时,我遇到了同样的问题。

好消息是流行的应用程序(YouTube 和其他)没有这个问题。我找到了信息资源。经过调查,我提出了一个对我来说方便的解决方案。关键是用Presenter代替Adapter 有最简单的例子

//Presenter class
public class ItemViewPresenter extends Presenter {

    @Override
    public final ViewHolder onCreateViewHolder(ViewGroup parent) {

        //I use data binding
        ItemBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.item, parent, false);
        return new MyViewHolder(binding);
    }

    @Override
    public final void onBindViewHolder(ViewHolder viewHolder, Object item) {
        String text = (String) item;
        ((MyViewHolder) viewHolder).bind(text);
    }

    @Override
    public final void onUnbindViewHolder(ViewHolder viewHolder) {
    }

    private class MyViewHolder extends Presenter.ViewHolder {

        private final ItemBinding binding;

        private DiscoveryViewHolder(ItemBinding binding) {
            super(binding.getRoot());
            this.binding = binding;
        }

        private void bind(String text) {

            binding.textView.setText(text);
        }
    }
}

//... 
private void setupRecyclerView() {

    RecyclerView recyclerView = _baseLayout.findViewById(R.id.recyclerView);

    ArrayObjectAdapter arrayObjectAdapter = new ArrayObjectAdapter(new ItemViewPresenter());

    ItemBridgeAdapter bridgeAdapter = new ItemBridgeAdapter(arrayObjectAdapter);

    recyclerView.setAdapter(bridgeAdapter);

    LinearLayoutManager layoutManager = new LinearLayoutManager(_baseLayout.getContext(), LinearLayoutManager.HORIZONTAL, false);
    recyclerView.setLayoutManager(layoutManager);

    List<Strings> textList = new ArrayList(1);
    textList.add("1");

    //add objects
    arrayObjectAdapter.addAll(0, textList);

    //clear objects
    //arrayObjectAdapter.clear();
}
于 2018-01-17T20:05:48.910 回答