【问题标题】:RecyclerView scroll to bottom on insertion of new itemRecyclerView 在插入新项目时滚动到底部
【发布时间】:2020-08-12 06:32:01
【问题描述】:

我知道这个问题已经在here 中提出,但我的问题在插入项目的意义上有点不同。我也尝试了this帖子的所有解决方案,仍然没有运气。

背景:

我有一个RecyclerView,其项目已分为 3 列。第一个是TextView,其余的是EditText。最初,我向用户展示了一个仅包含一个项目的列表,其中 TextView 设置为 1(项目的位置),EditText 将填充一些值。一旦用户填充了EditText 并按下回车键,我将插入一个新项目,其中TextView 作为2(下一个项目的位置)和EditText,它们将被填充。在每次插入新项目时,我都想滚动到RecyclerView 的底部,以便用户可以轻松地编辑EditText。我不断插入新的项目单元用户点击Save 按钮,该按钮将把列表中的项目插入到数据库表中。

问题:

插入第 7 项后,RecyclerView 没有滚动到按钮,因此我使用以下代码对其进行了修复:

linearLayoutManager.setStackFromEnd(true);

使用上面的代码,我现在可以跳过 7 个项目,但是一旦我到达第 10 个项目,RecyclerView 就不会滚动到底部,所以我必须手动滚动。无论插入多少项目,我现在如何继续滚动?

我的代码:

适配器:

public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ViewHolder> {

    private List<ListModel> original;

    public ListAdapter(List<ListModel> list){ original = list; }

    @NonNull
    @Override
    public ListAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, 
                                                    int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View view = inflater.inflate(R.layout.list_layout, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ListAdapter.ViewHolder holder, 
                                 int position) {
        String sNo = original.get(position).getsNo();
        String product = original.get(position).getProduct();
        String price = original.get(position).getPrice();
        holder.sNo.setText(sNo);
        holder.product.setText(product);
        holder.product.requestFocus();
        holder.price.setText(price);
        holder.bind();
    }

    @Override
    public int getItemCount() { return original.size(); }

    public class ViewHolder extends RecyclerView.ViewHolder {
        EditText product, price;
        TextView sNo;
        public ViewHolder(View itemView){
            super(itemView);
            sNo = (TextView) itemView.findViewById(R.id.sno);
            product = (EditText) itemView.findViewById(R.id.newProduct);
            price = (EditText) itemView.findViewById(R.id.newPrice);
        }

        public void bind() {
            addListener(product);
            addListener(price);
        }

        private void addListener(final EditText editText){
            editText.setOnKeyListener(new View.OnKeyListener() {
                @Override
                public boolean onKey(View v, int keyCode, KeyEvent event) {
                    if (event.getAction() == KeyEvent.ACTION_UP && 
                        keyCode == KeyEvent.KEYCODE_ENTER) {
                        if (!anyEmptyEditText()){
                            // insert new empty row
                            ListModel item = new ListModel(
                                             String.valueOf(getItemCount()+1),
                                             "", "", "");
                            original.add(item);
                            notifyItemInserted(getItemCount());
                        } else {
                            if (editText == product)
                                price.requestFocus();
                            else if (editText == price)
                                product.requestFocus();
                        }
                    }else{
                        // modify adapter by keeping it consistent with 
                        // the data being inserted in `EditText`
                        ListModel item = new ListModel(String.valueOf(getItemCount()),
                                                      product.getText().toString(),
                                                      price.getText().toString());
                        original.set(getItemCount() - 1,item);
                    }
                    return false;
                }
            });
        }
    }

    private boolean anyEmptyEditText(){
        for (int idx = 0; idx < original.size(); idx++)
            if (original.get(idx).getProduct().isEmpty() || 
                original.get(idx).getPrice().isEmpty())
                return true;
        return false;
    }
}

活动:

public class FormActivity extends AppCompatActivity {
    
    private ArrayList<ListModel> list;
    private RecyclerView listView;
    private ListAdapter listAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_order_form);        
        setupAdapter();        
    }

    private void setupAdapter(){
        listView = (RecyclerView) findViewById(R.id.newTableContent);    
        final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setStackFromEnd(true);
        listView.setLayoutManager(linearLayoutManager);
        list = new ArrayList<>();
        listAdapter = new ListAdapter(list);
        listView.setAdapter(listAdapter);
    }    
}

我也想获得我的代码的优化版本。

【问题讨论】:

  • 有一些未被接受的答案可能会有所帮助:stackoverflow.com/a/52754932/7210237。这个想法是正确的 - 监听数据变化,当有变化时滚动到可用的最后一行,如果合适的话。

标签: android android-recyclerview


【解决方案1】:

我通过在插入新项目后让界面与活动对话来修复它,如下所示:

适配器:(创建和设置监听器)

private final NewItem listener;

public interface NewItem {
    void onNewItemInsert(boolean inserted);
}

public ListAdapter(List<ListModel> list, NewItem listener){
    original = list;
    this.listener = listener;
}

addListener() 我添加一个项目的地方,我将值设置为侦听器:

if (!anyEmptyEditText()){
    // reset of the code
    listener.onNewItemInsert(true);
}

Activity:(在setupAdapter() 内获取监听器并滚动到新创建的项目)

 private void setupAdapter(){
    // reset of the code
    listAdapter = new ListAdapter(list, new ListAdapter.NewItem() {
          @Override
          public void onNewItemInsert(boolean inserted) {
              if (inserted)
                 listView.scrollToPosition(listAdapter.getItemCount() - 1);
          }
    });
    // reset of the code
 }

事件虽然解决了原来的问题,但它引入了两个小问题,分别是:

在插入新项目时,RecyclerView 似乎下降了一点,然后又回到了原来的位置,requestFocus() 总是应用于最后一个正在考虑的EditText。我希望 requestFocus() 在插入新项目时始终位于第一个 EditText 上。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-09
    • 1970-01-01
    • 2018-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多