RecyclerView项目失去焦点

时间:2015-12-14 22:00:21

标签: android android-recyclerview linearlayoutmanager

在我的防火电视应用中,我使用recyclerview horizontal layout

使用dpad进行滚动工作以及项目正在获得关注。

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

它看起来像一个bug。有没有解决方法呢?

5 个答案:

答案 0 :(得分:3)

我面临同样的问题,我在我的项目中所做的事情在我的Activity(包含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中正常工作。

答案 1 :(得分:2)

我认为@ 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();
    }
}

答案 2 :(得分:1)

看起来这是一个错误。

请参阅https://stackoverflow.com/a/33190656/332798https://issuetracker.google.com/issues/37067220

我能够通过在我的项目视图上中断override fun clearFocus() { if (parent != null) super.clearFocus() } 来解决这个错误,因此失去焦点的分离视图不会将焦点移到RecyclerView之外:

T=readtable('H:/Temporary/test.csv');
T.Properties.VariableNames = {'Devices' 'Time'};
Devices1=T.Devices;
Time1=T.Time;
hist(Devices1, Time1);

答案 3 :(得分:0)

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

notifyItemChanged(position);

答案 4 :(得分:-1)

我遇到了同样的问题。好消息是热门应用程序(YouTube和其他人)没有这个问题。 我找到了提供信息的resource。经过调查,我找到了一个方便我的解决方案。 关键是使用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();
}