我在recyclerview中有一个mapview,但是我在尝试使mapview中的事件由地图本身而不是recyclelerviewer处理时遇到问题。我发现this向我展示了我应该用getParent()覆盖dispatchTouchEvent方法.requestDisallowInterceptTouchEvent(true)。 好吧,它确实让地图回应了触摸事件,但不知何故,地图上的任何触摸都触发了父级RecyclerView上的OnLongClick,我只是无法理解为什么/如何。这是代码:
public class MainActivity extends AppCompatActivity {
private RecyclerView rv;
private int currentSelected =-1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayoutManager llm = new LinearLayoutManager(this);
llm.setOrientation(LinearLayoutManager.VERTICAL);
rv = findViewById(R.id.recycler_view);
rv.setLayoutManager(llm);
LatLng eifel = new LatLng(48.858093, 2.294694);
LatLng liberty = new LatLng(40.689247, -74.044502);
LatLng vatican = new LatLng(41.906487, 12.453641);
ArrayList<LatLng> l = new ArrayList<LatLng>();
l.add(eifel); l.add(liberty) ; l.add(vatican);
rv.setAdapter(new Adapter(l));
rv.addOnItemTouchListener(new RecyclerItemListener(getApplicationContext(), rv, new RecyclerItemListener.RecyclerTouchListener() {
@Override
public void onClickItem(View v, int position) {
}
public void onLongClickItem(final View v, int position) {
Toast.makeText(MainActivity.this, "onLongClick", Toast.LENGTH_SHORT).show();
if (currentSelected == position)
destroyMap(position);
else
prepareMaps(position);
}
})
);
}
public void prepareMaps(final int position) {
final Adapter.MyViewHolder holder = ( Adapter.MyViewHolder)rv.findViewHolderForAdapterPosition(position);
final LatLng selected = ((Adapter)rv.getAdapter()).getItem(position);
if (!holder.mapsCreated) {
holder.mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(final GoogleMap googleMap) {
LatLng place = new LatLng(selected.latitude, selected.longitude);
googleMap.addMarker(new MarkerOptions().position(place).title("Marker"));
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(place)
.zoom(16)
.build();
googleMap.moveCamera(CameraUpdateFactory
.newCameraPosition(cameraPosition));
}
});
holder.mapView.onCreate(null);
holder.mapView.onStart();
holder.mapView.onResume();
holder.mapsCreated = true;
}
else {
holder.mapView.onResume();
}
currentSelected = position;
holder.container.setVisibility(View.VISIBLE);
}
public void destroyMap(int position) {
Adapter.MyViewHolder holder = ( Adapter.MyViewHolder)rv.findViewHolderForAdapterPosition(position);
holder.container.setVisibility(View.GONE);
if (holder.mapsCreated)
holder.mapView.onPause();
currentSelected = -1;
}
class Adapter extends RecyclerView.Adapter<Adapter.MyViewHolder> {
ArrayList<LatLng> locations;
class MyViewHolder extends RecyclerView.ViewHolder{
TextView text;
LinearLayout container;
MapView mapView;
boolean mapsCreated = false;
MyViewHolder(View view) {
super(view);
text = view.findViewById(R.id.latlng);
container = view.findViewById(R.id.container);
mapView = view.findViewById(R.id.mapView);
}
}
public Adapter(ArrayList<LatLng> locations) {
this.locations=locations;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.simple_row,parent, false);
return new Adapter.MyViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, final int position) {
String lat = String.valueOf(locations.get(position).latitude);
String lng = String.valueOf(locations.get(position).longitude);
holder.text.setText("Location: \nLat: " + lat + "\nLong:" + lng+ "\n");
}
@Override
public int getItemCount() {
return locations.size();
}
public LatLng getItem(int position) {
return locations.get(position);
}
}
}
class RecyclerItemListener implements RecyclerView.OnItemTouchListener {
private RecyclerTouchListener listener;
private GestureDetector gd;
public interface RecyclerTouchListener {
public void onClickItem(View v, int position) ;
public void onLongClickItem(View v, int position);
}
public RecyclerItemListener(Context ctx, final RecyclerView rv, final RecyclerTouchListener listener) {
this.listener = listener;
gd = new GestureDetector(ctx,
new GestureDetector.SimpleOnGestureListener() {
@Override
public void onLongPress(MotionEvent e) {
View v = rv.findChildViewUnder(e.getX(), e.getY());
listener.onLongClickItem(v, rv.getChildAdapterPosition(v));
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
View v = rv.findChildViewUnder(e.getX(), e.getY());
listener.onClickItem(v, rv.getChildAdapterPosition(v));
return true;
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
return ( child != null && gd.onTouchEvent(e));
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
class CustomMapView extends MapView {
public CustomMapView(Context context) {
this(context,null);
}
public CustomMapView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
getParent().requestDisallowInterceptTouchEvent(true);
return super.dispatchTouchEvent(ev);
}
}
有人能告诉我为什么当我试图移动地图或点击地图时会调用onLongClick吗?如果它只是一次点击就没关系,onLongClick是在recyclerview中调用的。
谢谢!
答案 0 :(得分:0)
rv.addOnItemTouchListener(new RecyclerItemListener(getApplicationContext(), rv, new RecyclerItemListener.RecyclerTouchListener() {
@Override
public void onClickItem(View v, int position) {
}
public void onLongClickItem(final View v, int position) {
Toast.makeText(MainActivity.this, "onLongClick", Toast.LENGTH_SHORT).show();
if (currentSelected == position)
destroyMap(position);
else
prepareMaps(position);
}
})
);
首先,你已经设置了touchlerview项目的触摸监听器,所以当你只是触摸视图时它总是被调用,而你已经设置了onLongClickItem方法,所以我建议你把那个方法放在触摸监听器范围之外,如果您希望在长按下执行操作,而不是使用正确的onLonglClickListener
将其设置在特定项目视图上