在插入新项目时,RecyclerView滚动到底部

时间:2020-08-12 06:32:01

标签: android android-recyclerview

我知道here中已经问过这个问题,但是我的问题在插入项目的方式上有点不同。我还尝试了this的所有解决方案,但仍然没有运气。

背景

我有一个RecyclerView,其项目已分为3列。第一个是TextView,其余的是EditText。最初,我为用户提供一个列表,其中只有一个项目,其TextView设置为1(项目的位置),并且EditText将填充一些值。一旦用户同时填充了两个EditText并按下Enter键,我将插入一个新项目,其中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);
    }    
}

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

1 个答案:

答案 0 :(得分:0)

我通过在插入新项后通过界面与活动对话来解决它:

Adapater:(创建并设置侦听器)

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);
}

活动 :(在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上。