2016-05-26 22 views
12

Trong một trong số questions trước đó của tôi, tôi đã hỏi (và tự trả lời bài đăng trên blog this) về cách xử lý chính xác đầu vào chính trên RecyclerView.Thêm hỗ trợ bàn phím thích hợp vào RecyclerView

Bây giờ tôi nhận ra rằng nếu tôi giữ phím mũi tên, hãy nhấn phím xuống, các điểm dừng di chuyển xuống và số RecyclerView sẽ mất tiêu điểm, có thể do cuộn nhanh hơn thế hệ của tất cả các trẻ em View s.

Có cách giải quyết nào hay thực hành tốt hơn để xử lý đúng cách đầu vào bàn phím phần cứng trên RecyclerView không?

Cập nhật:

tôi xuất bản một ví dụ cơ bản here, nó hoạt động hoàn hảo bây giờ, không tập trung hơn thua lỗ.

+2

Đỗ bạn có một [mcve]? Tôi vừa thêm hỗ trợ bàn phím vào một 'RecyclerView' ngày hôm qua, dọc theo dòng cách bạn đang thực hiện nó. Trong trường hợp của tôi, đó là một 'RecyclerView' toàn màn hình, vì vậy tôi không có bất kỳ vấn đề tiêu điểm nào. Nó sẽ dễ dàng hơn cho mọi người để giúp bạn vượt qua một vấn đề nếu chúng ta có một thực hiện cụ thể của vấn đề. – CommonsWare

+0

@CommonsWare Tôi sẽ tạo ví dụ của tôi càng sớm càng tốt. Tôi nghĩ bạn có thể thử thêm chế độ xem có thể lấy nét (ví dụ: nút) bên dưới RecyclerView của bạn và sử dụng tập dữ liệu lớn trong bộ điều hợp, giả sử là 100 mục. Bạn sẽ thấy trọng tâm hành xử kỳ lạ. – Vektor88

+0

Tôi sẽ poke vào ngày mai này. Tôi đã thấy các kết quả khác lạ (ví dụ: hiệu ứng bôi nhọ). Tôi nghĩ có lẽ chúng ta cần phải đợi để cập nhật 'RecyclerView' lần thứ hai cho đến sau lần đầu tiên xử lý xong, thay vì một lần cho mỗi sự kiện quan trọng. Tất cả những gì đang được nói, có một cái nhìn tập trung bên dưới một danh sách theo chiều dọc di chuyển không phải là một bàn phím tốt UX ở nơi đầu tiên. Bạn sẽ thấy cuộc thảo luận về loại điều đó trong phạm vi bao gồm các ứng dụng viết cho Android TV (hoặc người tiền nhiệm Google TV, Fire TV, v.v.). – CommonsWare

Trả lời

4

tôi quản lý để thực hiện một lớp Adaptor trừu tượng có khả năng theo dõi các mục đã chọn mà không làm mất mục tiêu, một dự án mẫu có thể được tìm thấy here, việc thực hiện cụ thể của lớp adapter là dưới đây:

import android.content.Context; 
import android.support.v7.widget.RecyclerView; 
import android.view.KeyEvent; 
import android.view.View; 


/** 
* Created by vektor on 31/05/16. 
*/ 
public abstract class InputTrackingRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH>{ 

    private Context mContext; 
    private int mSelectedItem = 0; 
    private RecyclerView mRecyclerView; 

    public InputTrackingRecyclerViewAdapter(Context context){ 
     mContext = context; 
    } 

    @Override 
    public void onAttachedToRecyclerView(final RecyclerView recyclerView) { 
     super.onAttachedToRecyclerView(recyclerView); 

     mRecyclerView = recyclerView; 
     // Handle key up and key down and attempt to move selection 
     recyclerView.setOnKeyListener(new View.OnKeyListener() { 
      @Override 
      public boolean onKey(View v, int keyCode, KeyEvent event) { 
       RecyclerView.LayoutManager lm = recyclerView.getLayoutManager(); 

       // Return false if scrolled to the bounds and allow focus to move off the list 
       if (event.getAction() == KeyEvent.ACTION_DOWN) { 
        if (isConfirmButton(event)) { 
         if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) == KeyEvent.FLAG_LONG_PRESS) { 
          mRecyclerView.findViewHolderForAdapterPosition(mSelectedItem).itemView.performLongClick(); 
         } else { 
          event.startTracking(); 
         } 
         return true; 
        } 
        else { 
         if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { 
          return tryMoveSelection(lm, 1); 
         } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { 
          return tryMoveSelection(lm, -1); 
         } 
        } 
       } 
       else if(event.getAction() == KeyEvent.ACTION_UP && isConfirmButton(event) 
         && ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != KeyEvent.FLAG_LONG_PRESS)){ 
        mRecyclerView.findViewHolderForAdapterPosition(mSelectedItem).itemView.performClick(); 
        return true; 
       } 
       return false; 
      } 
     }); 
    } 

    private boolean tryMoveSelection(RecyclerView.LayoutManager lm, int direction) { 
     int nextSelectItem = mSelectedItem + direction; 

     // If still within valid bounds, move the selection, notify to redraw, and scroll 
     if (nextSelectItem >= 0 && nextSelectItem < getItemCount()) { 
      notifyItemChanged(mSelectedItem); 
      mSelectedItem = nextSelectItem; 
      notifyItemChanged(mSelectedItem); 
      //lm.scrollToPosition(mSelectedItem); 
      mRecyclerView.smoothScrollToPosition(mSelectedItem); 
      return true; 
     } 

     return false; 
    } 

    public Context getContext(){ return mContext; } 

    public int getSelectedItem() { return mSelectedItem; } 
    public void setSelectedItem(int selectedItem) { mSelectedItem = selectedItem; } 

    public RecyclerView getRecyclerView() { return mRecyclerView; } 


    @Override 
    public void onBindViewHolder(VH holder, int position) { 
     onBindViewHolder(holder, position); 
    } 

    public static boolean isConfirmButton(KeyEvent event){ 
     switch (event.getKeyCode()){ 
      case KeyEvent.KEYCODE_ENTER: 
      case KeyEvent.KEYCODE_DPAD_CENTER: 
      case KeyEvent.KEYCODE_BUTTON_A: 
       return true; 
      default: 
       return false; 
     } 
    } 


} 
Các vấn đề liên quan