2012-06-19 18 views
3

到目前爲止,我已經搜索了幾個小時,並沒有找到任何適合我的問題的解決方案。onTouchListener for TableRow中的多個TextViews

我擺弄着我的android應用程序,並試圖做一個數獨遊戲。

TableLayout由9個TableRows組成,每個TableRows包含9個TextViews。 因此,9 * 9格包含81個TextViews各自具有OnTouchListener:

final OnTouchListener cellTouch = new OnTouchListener() { 
    public boolean onTouch(View v, MotionEvent e) { 
     Log.d("TOUCH", "id: "+v.getId() + " "+e.toString()); 

     final int action = e.getAction(); 

     switch (action) { 
      case MotionEvent.ACTION_DOWN: { 
       // set background to different colour 
       // set background back if this is different TextView 

       break; 
      } 
      case MotionEvent.ACTION_MOVE: { 

       break; 
      }    
     } 

     return true; 
    }  
}; 

的OnTouch獲取在每個單獨的TextView燒製,但是觸摸之一,移動軌跡球圍繞以下後發生:

  • ACTION_DOWN
  • 數ACTION_MOVE的
  • ACTION_UP

但是,我想要的是OnTouch在其他TextView上觸發並使其突出顯示。 我創建了一個單元的方式如下:

  TextView cellLabel = (TextView) inflater.inflate(R.layout.sudoku_cell, tr, false); 
      cellLabel.setId(curCellId); 
      cellLabel.setText(""+ curCellId); 

      cellLabel.setOnTouchListener(cellTouch); 
      cellLabel.setOnFocusChangeListener(cellFocus); 
      cellLabel.setOnClickListener(cellClick); 
      cellLabel.setFocusable(true); 
      cellLabel.setClickable(true); 
      cellLabel.setFocusableInTouchMode(true); 

每個單獨的小區:

<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_height="35dp" 
android:layout_weight="1" 
android:textSize="18dp" 
android:textColor="#FFFFFF" 
android:gravity="center" 
android:background="@layout/border" 
/> 

我一直在嘗試很多不同的東西。比如確定TextView的指針位於頂部,但沒有任何運氣。

希望你們任何人都有一個主意。感謝您的時間。

親切的問候。

EDIT

通過TextView的[] [],並找到合適的小區搜索功能來循環。但是,只能在連續的基礎上工作。如果我從一行切換到另一行,它不起作用。

private TextView getCell (View v, MotionEvent e) { 
    float x = e.getX(); 
    float y = e.getY(); 

    for (int i = 0; i < GRID_HEIGHT; i++) { 
     for (int j = 0; j < GRID_WIDTH; j++) { 
      TextView tv = tvGrid[i][j]; 

      Rect rectView = new Rect(tv.getLeft(), tv.getTop(), tv.getRight(), tv.getBottom());   

      if(rectView.contains((int)x, (int)y)) { 
       return tv; 
      } 
     } 
    } 

    return null; 
} 
+0

一旦視圖已經表示將處理觸摸對方的意見不會得到事件,直到一個後續行動。看到亞歷克斯的回答如下,這幾乎是我過去做這項工作的方式 – Idistic

+0

這正是發生的情況。將考慮亞歷克斯的建議。 – LordOfBones

回答

2

這裏是我試過自己的代碼:

佈局只是3個TableRows一個TableLayout,每個包含的TableRow 3個TextViews與像T1,T2的ID,..,T9

而且活動:

public class ImgActivity extends Activity { 

protected Map<View, Rect> cells = new HashMap<View, Rect>(); 

protected boolean hasCoordinatesPopulated; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    final TableLayout table = (TableLayout) findViewById(R.id.table); 
    table.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
     @Override 
     public void onGlobalLayout() { 
      if (!hasCoordinatesPopulated) { 
       View view = table.findViewById(R.id.t1); 
       Rect rect = getRawCoordinatesRect(view); 
       cells.put(view, rect); 

       view = table.findViewById(R.id.t2); 
       rect = getRawCoordinatesRect(view); 
       cells.put(view, rect); 

       view = table.findViewById(R.id.t3); 
       rect = getRawCoordinatesRect(view); 
       cells.put(view, rect); 

       view = table.findViewById(R.id.t4); 
       rect = getRawCoordinatesRect(view); 
       cells.put(view, rect); 

       view = table.findViewById(R.id.t5); 
       rect = getRawCoordinatesRect(view); 
       cells.put(view, rect); 

       view = table.findViewById(R.id.t6); 
       rect = getRawCoordinatesRect(view); 
       cells.put(view, rect); 

       view = table.findViewById(R.id.t7); 
       rect = getRawCoordinatesRect(view); 
       cells.put(view, rect); 

       view = table.findViewById(R.id.t8); 
       rect = getRawCoordinatesRect(view); 
       cells.put(view, rect); 

       view = table.findViewById(R.id.t9); 
       rect = getRawCoordinatesRect(view); 
       cells.put(view, rect); 

       hasCoordinatesPopulated = true; 
      } 
     } 

     private Rect getRawCoordinatesRect(final View view) { 
      int[] coords = new int[2]; 
      view.getLocationOnScreen(coords); 
      Rect rect = new Rect(); 
      rect.left = coords[0]; 
      rect.top = coords[1]; 
      rect.right = rect.left + view.getWidth(); 
      rect.bottom = rect.top + view.getHeight(); 
      return rect; 
     } 
    }); 
    table.setOnTouchListener(new OnTouchListener() { 
     @Override 
     public boolean onTouch(final View v, final MotionEvent event) { 
      if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) { 
       final int x = (int) event.getRawX(); 
       final int y = (int) event.getRawY(); 
       for (final Entry<View, Rect> entry : cells.entrySet()) { 
        final View view = entry.getKey(); 
        final Rect rect = entry.getValue(); 
        if (rect.contains(x, y)) { 
         view.setBackgroundColor(Color.CYAN); 
        } else { 
         view.setBackgroundColor(Color.TRANSPARENT); 
        } 
       } 
       return true; 
      } 
      return false; 
     } 
    }); 
} 

}

當然這是一個快速樣品變種。您可以將您上次選擇的視圖存儲在單獨的字段中(以取消選擇移動),並找到指針下方的元素時,只需循環break即可節省一些時間。

0

你有沒有試過如下:

  1. 您的所有textviews的原始座標和地圖項目,將它們存儲關鍵是你的TextView(或ID)和值是它的座標的矩形和它需要的空間。

  2. 設置您的tableview的ontouchlistener,然後,當用戶移動,或觸摸的東西,你可以得到的指針的原始座標,遍歷地圖項,找到的TextView目前低於

P.S.這是我想到的第一個想法。我很確定android可以提供更優雅的解決方案。

+1

這是過去爲我工作的方法,儘管我使用覆蓋來處理觸摸,並將其直接附加到它可以工作的特定視圖。 – Idistic

+0

1)應該再試一次。我所擁有的是一個9 * 9的TextView矩陣,並通過它們循環找到指針下方的那個。 我會再看看這個,看看你的解決方案是否有效。 感謝您的建議。 – LordOfBones

+0

到目前爲止,我只在每行的基礎上工作,因爲TextView的位置取自父級的角度。在原始文章中,您可以看到搜索功能。我可以做的是給TableRow一個ID,比如100-108,並在搜索單元格時使用它來索引行。 – LordOfBones

0

現在工作就像一個魅力。感謝一束:>

編輯:添加handleCell()

// Initialization 
grid.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
     public void onGlobalLayout() { 
      if (!populatedCells) { 
       handlePopulate(); 
       populatedCells = true; 
      } 
     } 
    }); 

private void handlePopulate() { 
    int curCellId = 0; 

    for (int i = 0; i < GRID_HEIGHT; i++) { 
     for (int j = 0; j < GRID_WIDTH; j++) { 
      TextView tv = (TextView) findViewById(curCellId); 
      Rect rect = getRawCoordinatesRect(tv); 
      Log.d("RECT", "id: "+tv.getId()+" "+rect.toString()); 

      cells.put(tv, rect); 

      curCellId++; 
     } 
    } 
} 


// Listener 
final OnTouchListener cellTouch = new OnTouchListener() { 
    public boolean onTouch(View v, MotionEvent e) { 

     final int action = e.getAction(); 

     switch (action) { 
      case MotionEvent.ACTION_DOWN:    
      case MotionEvent.ACTION_MOVE: { 
       handleCell(v,e); 

       break; 
      }    
     } 

     return true; 
    }  
}; 

private TextView getCell (View v, MotionEvent e) { 
    int x = (int) e.getRawX(); 
    int y = (int) e.getRawY(); 

    for (final Entry<View, Rect> entry : cells.entrySet()) { 
     final View view = entry.getKey(); 
     final Rect rect = entry.getValue(); 

     if(rect.contains(x, y)) { 
      return (TextView) view; 
     } 
    } 

    return null; 
} 

private void handleCell (View v, MotionEvent e) { 
    TextView cell = getCell(v, e); 

    if (cell != null) {   
     cell.setBackgroundResource(R.layout.border_cell_current); 

     curCell = (TextView) cell; 

     // do something 
    } 
} 
+0

我編輯了一下我的代碼,並將該行更改爲rect.bottom = rect.top + view.getHeight(); (之前是view.getBottom(),這是不正確的) –