0

我很难弄清楚这一点。我有 8 个按钮的网格视图。目前我正在使用 onItemClickListener 来触发按钮操作,但这给我带来了两个问题。

1) 按钮动作发生在按钮未按下后。

2)两个按钮不能同时按下,必须松开第一个按钮。

据我所知,onTouchListener 应该可以解决我的第一个问题,尽管我不确定如何确定按下了哪个按钮。我的 onItemClickListener 代码如下

gridview.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View v, int position, long id) {

        Toast.makeText(Activity.this, "" + position, Toast.LENGTH_SHORT).show();

  }
        });

现在有了以上内容,我确切地知道按下了哪个按钮。我相信实现为 onTouchListener 的代码如下

        gridview.setOnTouchListener(new OnTouchListener() {

        public boolean onTouch(View v, MotionEvent event) {
            return false;
        }
    }) {

我应该如何确定使用 MotionEvent 按下了哪个按钮?在我通过“职位”之前,这让这件事变得相当容易。我还需要考虑是否同时按下了两个或多个按钮/没有放开另一个按钮。

有谁知道如何实现这一目标?

4

3 回答 3

1

最近遇到了这个问题并在寻求帮助时遇到了这篇文章,我想从我所做的事情中添加两件似乎有效的事情:

1)我将 onTouchListener 添加到适配器中的对象而不是活动或网格视图。

2) 在 OnTouchListener 中,我查找了 MotionEvent.ACTION_DOWN(第一次手指触摸)和 MotionEvent.ACTION_POINTER_DOWN(随后的手指触摸),这样我就可以获得多点触摸并立即处理它们,而无需等待用户抬起手指。

请注意,我将其命名为 ImageAdapter,即使我已经为每个都添加了一个 TextView,因为这样我可以将 TextView 背景用于图像,但将不可见的文本添加到 TextView 以便它与 Talkback 一起使用):

public class ImageAdapter extends BaseAdapter {
    private Context mContext;

    public ImageAdapter(Context c) {
        mContext = c;
    }

    public int getCount() {
        return numCols * numRows;
    }

    public Object getItem(int position) {
        return this;
    }

    public long getItemId(int position) {
        return position;
    }

    // create a new TextView for each item referenced by the Adapter
    public View getView(int position, View convertView, ViewGroup parent) {
        TextView textView;

        if (convertView == null) {  // if it's not recycled, initialize some attributes
            textView = new TextView(mContext);

        } else {
            textView = (TextView) convertView;
        }

        // place any other initial setup needed for the TextView here

        // here's our onTouchListener
        textView.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                boolean returnValue;
                int thePosition = v.getId();

                // MotionEvent.ACTION_DOWN gets the first touch
                // MotionEvent.ACTION_POINTER_DOWN gets any subsequent touches (if you place a second finger on the screen)
                // Between these I can get touches as soon as they happen, including multitouch support, without needing to wait until the user lifts their finger.

                if ((event.getAction() == MotionEvent.ACTION_DOWN) || (event.getAction() == MotionEvent.ACTION_POINTER_DOWN)) {
                    TextView textView;
                    if (v == null) {  // if it's not recycled, initialize some attributes
                        textView = new TextView(mContext);

                    } else {
                        textView = (TextView) v;
                    }

                    // Do any processing based on the touch - I call a function and pass the position (number of cell, 1..n) and textview so can make changes to it as needed
                    ScreenTapped(thePosition, textView);
                    // I used a returnValue
                    returnValue = true;
                } else returnValue = false;

                return returnValue;

        });
        return textView;

    } // getView
} //imageadapter
于 2015-02-03T22:29:46.653 回答
0

使用 gridView 时的理念是:

  • 网格视图实现了 onTouchLister
  • 当触摸发生时 onTouchLister 为所有 ACTION_MOVE 事件收集坐标(很多:))
  • 当触摸事件为MOVE_UP时,计算坐标下的真实位置并返回网格中的item

所以解决方案是:

在您有findViewById(some_grid_view)的活动中

//Register handler for the onTouch event of gridView in your activity
gridView.setOnTouchListener(new MyActivityOnTouchListener(this));

注意:我的 onTouch 监听器是在另一个类 (MyActivityOnTouchListener) 中实现的,而不是在活动内部

...然后在 MyActivityOnTouchListener 类中实现onTouch方法:

public class CalendarActivityOnTouchListener implements View.OnTouchListener {
    private MyActivity myActivityContext; 
    private GridView mGridView;
    private HashSet<Point> movementCoordinates = new HashSet<Point>;

    //Constructor
    public MyActivityOnTouchListener (MyActivity context){
        this.myActivityContext= context;
        mGridView= myActivityContext.getGridView();  //assign touched gridView into a local variable
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {

    /*
     *   NOTE: 
     *    ACTION_MOVE fires events until you release it
     *    ACTION_UP once you release it fires it   
     */

    //while touching the grid a bunch of ACTION_MOVE events are dispatched
    if (event.getAction() == MotionEvent.ACTION_MOVE) {
       //gather all coordinates touched (in a set to avoid duplicates)
       movementCoordinates.add(new Point((int)event.getX(), (int)event.getY()));
       return true;
    }

    //Finally the finger is lifted   
    if (event.getAction() == MotionEvent.ACTION_UP) {

         //convert all movementCoordinates gathered in the previous block into real grid positions
        int position;
        for(Point p : movementCoordinates){
            Log.d("Luka", p.x +" / "+p.y);
            position = calendarGridView.pointToPosition(p.x, p.y);

            //...Do whatever with the position
        }
    }
  }

}

请注意pointToPosition()方法,因为在某些情况下它可以返回 -1 而不是坐标后面的位置。例如,如果网格中的项目之间有边距,则这些坐标无法返回位置,因此 -1

希望能帮助到你...

于 2013-05-28T10:51:10.380 回答
0

我实际上是想弄清楚同样的事情。我已经使用以下代码确定了单击了哪个网格单元

public boolean onTouch(View v, MotionEvent me) {

            float currentXPosition = me.getX();
            float currentYPosition = me.getY();
            int position = gridView.pointToPosition((int) currentXPosition, (int) currentYPosition);

Position 为您提供gridView 上的数字,您可以按如下方式检索该特定项目

gridView.getItemAtPosition(position)

但这就是我卡住的地方。我的 gridView 中有 Textview 项目,我无法将项目转换为 textview 然后对其执行操作。

希望这可以帮助!

于 2012-12-10T21:59:37.917 回答