Я добавляю кнопки динамически в вид сетки через его адаптер.У каждой кнопки есть следующие прослушиватели:
- при прослушивании щелчка: в данный момент просто печатает в консоли, что кнопка была нажата
- при прослушивании при длинном щелчке: запускает событие перетаскивания
- on слушатель перетаскивания: обрабатывает событие перетаскивания. В сеточном адаптере у меня есть
Arraylist<Button>
, к которому я добавляю кнопки.Мой метод getView()
возвращает соответствующий вид из списка.
Первое событие перетаскивания обрабатывается, как и ожидалось.Однако, если я нажимаю на кнопки после этого, они не отвечают.Я должен нажать ~ 10 раз, прежде чем все 10 сообщений попадут в консоль.Даже тогда я не могу долго нажимать на кнопки, чтобы перетаскивать их.
Я следовал многим учебным пособиям и многим другим советам, связанным с использованием ViewHolders и надуванием представлений в методе getView()
метода BaseAdapter
, но на самом деле не подходитменя, так как я получаю свои данные из базы данных.
Вот мои фрагменты кода:
MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GridView gridView = findViewById(R.id.gridView);
GridAdapter adapter = new GridAdapter();
gridView.setAdapter(adapter);
for(int i = 0; i < 2; i++) {
final String text = "Hello " + (i + 1);
Button button = new Button(MainActivity.this);
button.setText(text);
adapter.addView(button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TAG", "Button " + text + " pressed");
}
});
button.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
View.DragShadowBuilder myShadow = new View.DragShadowBuilder(v);
v.startDrag(null, myShadow, v, 0);
return true;
}
});
button.setOnDragListener(new DragEventListener());
button.setTag("1" + i);
}
}
DragEventListener.java
private class DragEventListener implements View.OnDragListener {
@Override
public boolean onDrag(View v, DragEvent event) {
final int action = event.getAction();
switch(action) {
case DragEvent.ACTION_DRAG_STARTED:
return v instanceof Button;
case DragEvent.ACTION_DRAG_ENTERED:
v.setVisibility(View.INVISIBLE);
return true;
case DragEvent.ACTION_DRAG_LOCATION:
return true;
case DragEvent.ACTION_DRAG_EXITED:
v.setVisibility(View.VISIBLE);
return true;
case DragEvent.ACTION_DROP:
if(event.getLocalState() == v) {
return false;
}
// this is the actual view being dropped
View itemBeingDragged = (View) event.getLocalState();
GridView itemsParent = (GridView) itemBeingDragged.getParent();
GridAdapter adapter = (GridAdapter) itemsParent.getAdapter();
adapter.swap(itemBeingDragged, v);
return true;
case DragEvent.ACTION_DRAG_ENDED:
v.setVisibility(View.VISIBLE);
return true;
}
return true;
}
}
И, наконец, GridAdapter.java
public class GridAdapter extends BaseAdapter {
private volatile ArrayList<View> children = new ArrayList<>();
public void addView(View view) {
children.add(view);
notifyDataSetChanged();
}
public void swap(View v1, View v2){
int indexOfV1 = children.indexOf(v1);
int indexOfV2 = children.indexOf(v2);
Collections.swap(children, indexOfV1, indexOfV2);
notifyDataSetChanged();
}
@Override
public int getCount() {
return children.size();
}
@Override
public Object getItem(int position) {
return children.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return children.get(position);
}
}
Есть идеи, что может произойти?Раньше я получал исключение после некоторого количества длинных кликов, связанных с NPE
, но сейчас я не могу воспроизвести его, чтобы показать исключение, к сожалению.
Я ценю любую помощь.