2017-05-16 3 views
1

J'ai travaillé sur la création de grille de Sudoku dont la valeur de cellule change chaque fois que je touche une cellule. J'ai donc implémenté cette grille de sudoku dans un LinearLayout by Child View, et j'ai essayé d'utiliser la méthode OnTouch, mais ça ne marche pas. J'ai essayé d'utiliser la méthode log pour vérifier si onTouch est réellement appelé, mais il semble que cette méthode soit parfaitement ignorée. J'ai cherché des solutions sur d'autres questions, mais il semble qu'aucune de ces solutions n'a aidé. Je me sens un peu craint ici, et toute aide serait grandement appréciée.[Android] onTouch dans l'enfant View ne répond pas

Voici mon code:

SudokuActivity.java

package snacker.nonogramsolver; 

import ...; /*many things are imported here*/ 

public class SudokuActivity extends AppCompatActivity { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_sudoku); 
    Button btn = (Button)findViewById(R.id.btn_clear); 
    Sudoku sdk = new Sudoku(this); 
    sdk.setOnTouchListener(sdk); 
} 

} 
; 

Sudoku.java

package snacker.nonogramsolver; 

import ...; 

public class Sudoku extends View implements View.OnTouchListener { 
    int mWidth = 9; 
    int mHeight = 9; 
    int mCellWidth, mCellHeight; 
    int mCellMargin; 
    int mEdgeThick; 
    int mStatus; 
    int mTextSize; 
    int mXNow = -1, mYNow = -1; 
    int[][] mBoard = new int[9][9]; 
    Point mBoardPt; 

    Paint mTextPaint, mTileEdgePaint; 

    final static int VALID = 0; 

    public Sudoku(Context context){ 
     super(context); 
     initializeBoard(); 
    } 

    public Sudoku(Context context, AttributeSet attrs){ 
     super(context, attrs); 
     initializeBoard(); 
    } 

    @Override 
    protected void onDraw(Canvas canvas){ 
     /* There are some codes here */ 
     Log.d("LogTest","OnDraw Complete"); 
    } 

    public void initializeBoard(){ 
     for (int x=0; x< mWidth; x++){ 
      for (int y=0; y< mHeight; y++){ 
       mBoard[x][y] = 0; 
      } 
     } 
     invalidate(); 
    } 

    public boolean onTouch(View v, MotionEvent event){ 
     Log.d("LogTest","Touched?"); /* LOG NOT ACTIVE HERE */ 
     if(event.getAction() == MotionEvent.ACTION_DOWN){ 
      mXNow = getBoardX(event.getX()); 
      Log.d("LogTest","" + mXNow); /* LOG NOT ACTIVE HERE */ 
      mYNow = getBoardY(event.getY()); 
      Log.d("LogTest","" + mYNow); /* LOG NOT ACTIVE HERE */ 
      mBoard[mXNow][mYNow] = mBoard[mXNow][mYNow] + 1; 
      invalidate(); 
      return true; 
     } 
     else return false; 
    } 

    int getBoardX(float scrx){ 
     int x = (int)((scrx)/mCellWidth); 
     if (x < 0) x = 0; 
     if (x > 8) x= 8; 
     return x; 
    } 
    int getBoardY(float scry){ 
     int y = (int)((scry)/mCellHeight); 
     if (y < 0) y = 0; 
     if (y > 8) y = 8; 
     return y; 
    } 
} 

Edit: fichier XML d'activité ajoutée.

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:orientation="vertical" 
    android:id="@+id/activity_sudoku" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:paddingBottom="@dimen/activity_vertical_margin" 
    android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    tools:context="snacker.nonogramsolver.SudokuActivity"> 

    <snacker.nonogramsolver.Sudoku 
     android:id="@+id/SudokuGrid" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" /> 

    <Button 
     android:id="@+id/btn_clear" 
     android:layout_width="150dp" 
     android:layout_height="30dp" 
     android:layout_weight="0.06" 
     android:text="Clear" /> 

</LinearLayout> 
+0

Je suppose que vous devez définir onTouchListener à cette coutume vue Sudoku en activité et gérer la méthode OnTouch() là-bas. Chose est que vous n'avez défini aucun auditeur. btw J'aime votre approche pour en faire une vue personnalisée –

+0

@GauravChauhan J'ai écouteur dans OnCreate dans SudokuActivity. Peut-être que ce n'était pas assez ou mauvaise approche? – SnackerH

+0

essayez de passer le contexte d'activité comme sdk.setOnTouchListener (this), et mettez en œuvre onTouch dans l'activité. –

Répondre

0

Vous ne pouvez pas ajouter directement touchListener par la simple création objet de classe Sudoku. Vous devriez ajouter view en XML ou par programmation.

Votre activité

public class MyActivity extends Activity{ 
    @Override 
protected void onCreate(Bundle savedInstanceState){ 
super.onCreate(savedInstanceState); 

//initializing custom views 
MyCustomView1 myCustomView1 = new MyCustomView1(parameterList); 
MyCustomView2 myCustomView2 = new MyCustomView2(parameterList); 

//adding both custom views to the main activity 
mainView.addView(myCustomView1); 
mainView.addView(myCustomView1); 

//adding custom listener to the custom view 1 
myCustomView1.setCustomEventListener(new OnCustomEventListener() { 

    @Override 
    public void onEvent() { 
     //firing an event of custom view 1 
     Toast.makeText(MainActivity.this, "Touched custom view 1", 
       Toast.LENGTH_SHORT).show(); 
    } 
}); 

//adding custom listener to the custom view 2 
myCustomView2.setCustomEventListener(new OnCustomEventListener() { 

    @Override 
    public void onEvent() { 
     //firing an event of custom view 2 
     Toast.makeText(MainActivity.this, "Touched custom view 2", 
       Toast.LENGTH_SHORT).show(); 
    } 
}); 
} 
} 

Votre CustomView 1

public class MyCustomView1 extends LinearLayout{ 
OnCustomEventListener myCustomEventListener; 

public MyCustomView1(ParameterList){ 
super(ContextFromParameterList); 
//Just adding something to the custom view 1 in order to distinguish it on the screen 
TextView tv = new TextView(ContextFromParameterList); 
tv.setText("Hello world from custom view 1"); 
addView(tv); 

this.setOnTouchListener(new OnTouchListener() { 

    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     //delegating one event to another (delegating touch event to custom event) 
     if (MyCustomView1.this.myCustomEventListener != null) 
      MyCustomView1.this.myCustomEventListener.onEvent(); 
     return false; 
    } 
}); } 

setCustomEventListener public void (OnCustomEventListener eventListener) {// réglage auditeur personnalisé à partir de l'activité myCustomEventListener = eventListener; }}

Votre CustomView2

public class MyCustomView2 extends LinearLayout { 
OnCustomEventListener myCustomEventListener; 

public MyCustomView2(ParameterList) { 
    super(ContextFromParameterList); 
//Just adding something to the custom view 1 in order to distinguish it on the screen 
TextView tv = new TextView(ContextFromParameterList); 
tv.setText("Hello world from custom view 2"); 
addView(tv); 

this.setOnTouchListener(new OnTouchListener() { 

    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     //delegating one event to another (delegating touch event to custom event) 
     if (MyCustomView2.this.myCustomEventListener != null) 
      MyCustomView2.this.myCustomEventListener.onEvent(); 
     return false; 
    } 
}); 
} 

    public void setCustomEventListener(OnCustomEventListener eventListener) { 
    //setting custom listener from activity 
    myCustomEventListener = eventListener; 
    } 
} 
Your listener interface: 

public interface OnCustomEventListener{ 
//interface defines one method. Can be more and methods may have parameters 
public void onEvent(); 
} 
+0

Oups, j'ai oublié de mentionner que j'ai ajouté l'affichage personnalisé dans le fichier xml ... – SnackerH

+0

Pouvez-vous ajouter ce code.Alors que je peux avoir une idée. – Dany

+0

Bien qu'il n'y a pas beaucoup de code là-dedans, mais fait. – SnackerH