Android:RecyclerView项目中的OnClickListener在模拟器和真实设备上的行为不同

时间:2016-05-04 14:21:45

标签: android android-emulator

我对Android开发很陌生 - 并且非常震惊:

我有一个Activity,显示添加了CardViews的RecyclerView。

每个CardView都附加了一个View.OnClickListener,每个CardView还包含一个附加了View.OnLongClickListener的ImageView。 此外,RecyclerView附加了一个RecyclerView.ItemTouchHelper以支持Drag(通过拖动整个CardView)和Swipe(通过在CardView中滑动ImageView,因此ImageView可以作为一种句柄)。

到目前为止,所有这些Listeners以及Dragging和Swiping在Android Studio中的模拟器(任何模拟的Android版本)上完美协调(使用鼠标点击)。但是当谈到真正的(Lollipop)设备(使用触摸)时,CardView中的OnClickListener似乎不再起作用了。它显示了单击该项目的视觉效果,但未调用onClick方法 - 就像点击/触摸事件未被识别或另一个“隐藏”侦听器捕获并消耗它。

如果在仿真器和真实设备上的行为相同,则很容易进行故障排除。但事实并非如此,我必须假设,任何(真实)设备上的行为都可能不同?

在模拟器和真实设备之间没有发现应用行为会有所不同的有用参考,但只是在模拟器中平稳运行时,应用甚至可能无法在真实设备上启动。任何想法?

这是我的听众的实现:

private class MyOnClickListener implements View.OnClickListener {

    private final Context context;

    public MyOnClickListener(Context context) {
        this.context = context;
    }

    @Override
    public void onClick(View v) {
        Log.i("ClickListener", "onClick fired");
        int selectedItemPosition = recyclerView.getChildAdapterPosition(v);
        Flight f = flightListRecyclerAdapter.getFlight(selectedItemPosition);
        if (data().getNewFlights().contains(f)) {
            data().getNewFlights().remove(f);
            flightListRecyclerAdapter.notifyItemChanged(selectedItemPosition);
        } else {

            Intent intent = new Intent(ShowFlightsActivity.this, EditFlightActivity.class);
            intent.putExtra(EditFlightActivity.FLIGHT_INFO, f);
            startActivity(intent);

        }

    }


}

private class MyOnLongClickListener implements View.OnLongClickListener {

    private final Context context;

    public MyOnLongClickListener(Context context) {
        this.context = context;
    }


    @Override
    public boolean onLongClick(View v) {
        Log.i("ClickListener", "onLongClick fired");
        int selectedItemPosition = recyclerView.getChildAdapterPosition((View) v.getParent().getParent());
        Flight f = flightListRecyclerAdapter.getFlight(selectedItemPosition);
        FlightListViewHolder viewHolder = (FlightListViewHolder) recyclerView.findViewHolderForAdapterPosition(selectedItemPosition);

        // toggle assumption of flight (but only for foreign flights)
        synchronized (LocalData.getInstance().getLock()) {
            if (f.getAssumptions() != null) {
                if (f.getAssumptions().size() == 0 || !f.getAssumptions().get(0).getAirport().equals(data().getOwnAirport())) {
                    assumeFlight(f);
                } else {
                    unassumeFlight(f);
                }
            }
            setCardBackground(ShowFlightsActivity.this, viewHolder.getCardView(), f);
        }


        return true;
    }
}

TouchHelperCallback:

public class FlightListItemTouchHelperCallback extends ItemTouchHelper.Callback {

private final FlightListItemTouchHelperAdapter adapter;

public FlightListItemTouchHelperCallback(FlightListItemTouchHelperAdapter adapter) {
    this.adapter = adapter;
}

@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    // support up and down movement
    int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
    int swipeFlags=0;
    if (viewHolder instanceof FlightListViewHolder) {
        FlightListViewHolder flightListViewHolder = (FlightListViewHolder) viewHolder;
        if (flightListViewHolder.dismissable) {
            swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
        }
    }
    return makeMovementFlags(dragFlags, swipeFlags);
}

@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
    adapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
    return true;
}

@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {

    adapter.onItemDismiss(viewHolder.getAdapterPosition());

}

@Override
public boolean isLongPressDragEnabled() {
    return true;
}

@Override
public boolean isItemViewSwipeEnabled() {
    return true;
}
}

在onCreateViewHolder()中从适配器内调用的静态方法(我将其解析为在另一个地方使用相同的功能 - 不同的活动,所以不应该是问题,我认为),这里的监听器是附加的到CardViews:

public static FlightListViewHolder createViewHolder(ViewGroup parent, Context context, boolean setListeners) {
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.flightlist_layout, parent, false);
    FlightListViewHolder flightListViewHolder = new FlightListViewHolder(view);
    ImageView leftImage = flightListViewHolder.leftImage;
    ImageView rightImage = flightListViewHolder.rightImage;
    if (setListeners) {
        view.setOnClickListener(ShowFlightsActivity.getMyOnClickListener());
        leftImage.setOnLongClickListener(ShowFlightsActivity.getMyOnLongClickListener());
        rightImage.setOnLongClickListener(ShowFlightsActivity.getMyOnLongClickListener());
    }

    return flightListViewHolder;
}
编辑:我想我现在看到了问题......我也在同一个cardView上设置一个OnTouchListener ......但是我仍然想知道它在模拟器中是如何工作的......

EDIT2:确实因为同时拥有OnTouchListener和OnClickListener而引发了问题。我终于通过覆盖我的CardView中的View.OnTouchEvent来解决它,如果触摸事件结果是点击(在此之后OnClickListener正常工作),则给出performClick():

@Override
public boolean onTouchEvent(MotionEvent e) {

    if (MotionEventCompat.getActionMasked(e) ==
            MotionEvent.ACTION_DOWN) {
        Log.i("ClickableCardView", "onTouch fired");
        impactPoint = e.getX();
    } else if (MotionEventCompat.getActionMasked(e) == MotionEvent.ACTION_UP) {
        if (impactPoint - e.getX() == 0) {
            Log.i("ClickableCardView", "this was a click");
            performClick();
        } else {
            Log.i("ClickableCardView", "this was a move: " + Float.toString(impactPoint - e.getX()));
        }
    }
    return true;

}

0 个答案:

没有答案