【问题标题】:Simultaneous GridView button events/determining which button has been touched同时 GridView 按钮事件/确定已触摸哪个按钮
【发布时间】:2015-02-04 06:29:46
【问题描述】:

我很难弄清楚这一点。我有 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 按下了哪个按钮?在我通过“职位”之前,这让这件事变得相当容易。我还需要考虑是否同时按下了两个或多个按钮/没有放开另一个按钮。

有谁知道如何做到这一点?

【问题讨论】:

    标签: android gridview touch-event ontouchlistener


    【解决方案1】:

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

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

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

    请注意,我将其命名为 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
    

    【讨论】:

      【解决方案2】:

      事实上,我正在尝试解决同样的问题。我已经使用以下代码弄清楚单击了哪个网格单元

      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 然后对其执行操作。

      希望这会有所帮助!

      【讨论】:

        【解决方案3】:

        使用 gridView 时的理念是:

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

        所以解决办法是:

        在您有 findViewById(some_grid_view)

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

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

        ...然后在 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

        希望对你有帮助……

        【讨论】:

          猜你喜欢
          • 2012-02-16
          • 2022-12-11
          • 2011-01-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-03
          • 1970-01-01
          相关资源
          最近更新 更多