在recyclelerview内部移动mapview,调用onLongClick

时间:2018-04-20 02:26:57

标签: android android-recyclerview android-mapview

我在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中调用的。

谢谢!

1 个答案:

答案 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

将其设置在特定项目视图上