3

これまで何時間も検索してきましたが、問題に対する適切な解決策が見つかりませんでした。

私のAndroidアプリケーションをいじって、数独ゲームを作ろうとしています。

TableLayoutは9つのTableRowで構成され、それぞれに9つのTextViewが含まれています。したがって、9 * 9グリッドには、それぞれがOnTouchListenerを持つ81個のTextViewが含まれています。

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で起動されますが、1つに触れてトラックボールを動かした後、次のことが発生します。

  • 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を決定するなど、ポインタが一番上にありますが、運がありません。

誰かがアイデアを持っていることを願っています。お時間をいただきありがとうございます。

敬具。

編集

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;
}
4

3 に答える 3

3

これが私が自分で試したコードです:

レイアウトは、3つのTableRowsを持つ単なるTableLayoutであり、各TableRowには、t1、t2、..、t9などのIDを持つ3つのTextViewが含まれています。

そして活動:

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、ループだけで時間を節約できます。

于 2012-06-20T07:21:51.310 に答える
0

次のことを試しましたか?

  1. すべてのテキストビューの生の座標を取得し、それらをマップに保存します。キーはTextView(またはID)であり、値はその座標と必要なスペースのRectです。

  2. テーブルビューにontouchlistenerを設定すると、ユーザーが移動したり、何かに触れたりしたときに、ポインターの生の座標を取得し、マップエントリを反復処理して、現在下にあるTextViewを見つけることができます。

PSこれは私の頭に浮かんだ最初のアイデアです。私はAndroidがよりエレガントなソリューションを提供できると確信しています。

于 2012-06-19T15:35:05.737 に答える
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
    }
}
于 2012-06-20T09:38:26.160 に答える