I have a gridview with custom buttons called bg_button in each cell. I am trying to create a boggle-like game and still a newbie in Android. I was searching through internet about this issue over a week now and still got nothing.
The issue is, when a touch_down I can get the specific item without any problem but when I start to move diagonal, I get multiple grid items that I do not want. For example;
A O F T
K T U L
T R S V
J O K U
The grid that I have above, when I touch T and then trying to move to O, I get;
T -> J -> O or T -> R -> O
I do not want J or R, but still I am touching that as well. I have tried to change to padding, or vertical and horizontal spacing but the issue remained the same. Could you please help me about this issue or at least can you give me a way to do this, or at least a specific tag that I can google and find information that can help me? Thank you so much for your time.
This is the part of my code for the touch event. I am saving the path to an ArrayList and I am sorry for the messy code. I will clean once I finish hardcoding:
final ArrayList<Integer> myList = new ArrayList<Integer>();
gridView = (GridView) this.findViewById(R.id.gridFriends);
MyAdapter gridAdapter = new MyAdapter(Boggler.this,board_1d);
gridView.setAdapter(gridAdapter);
gridView.setOnTouchListener(new View.OnTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event) {
final GridView layout = (GridView)v;
int action = event.getActionMasked();
float currentXPosition = event.getX();
float currentYPosition = event.getY();
int position = gridView.pointToPosition((int) currentXPosition, (int) currentYPosition);
// position = layout.pointToPosition( (int)event.getX(), (int)event.getY() );
while(position == -1)
position=event.getAction();
View v2 =layout.getChildAt(position);
myList.add(position);
Bg_button bt = (Bg_button) v2.findViewById(R.id.grid_item);
bt.setPressed(true);
Log.d(this.getClass().getName(), String.format("Over view.id[%d]", position));
if (action == MotionEvent.ACTION_MOVE){
myList.add(position);
return true;
}
if (action == MotionEvent.ACTION_UP) {
Log.d(this.getClass().getName(), myList.toString());
int i=0,j=0;
int state = 0;
Object[] st = myList.toArray();
for (Object s : st) {
if (myList.indexOf(s) != myList.lastIndexOf(s)) {
myList.remove(myList.lastIndexOf(s));}
else {
v2 =layout.getChildAt(myList.get(myList.lastIndexOf(s)));
bt = (Bg_button) v2.findViewById(R.id.grid_item);
bt.setPressed(false);
name = name + bt.getText();
Log.d(this.getClass().getName(), name);
}
}
And this is the xml files that I am using button_boggler:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.example.proje_test.bg_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.example.proje_test.Bg_button
android:id="@+id/grid_item"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center"
android:clickable="false"
android:textAppearance="?android:attr/textAppearanceMedium"
android:background="@drawable/color_bg_selector"
android:textSize="50dp"
/>
</LinearLayout>
And activity_boggler:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:orientation="vertical" >
<GridView
android:id="@+id/gridFriends"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:clipChildren="true"
android:columnWidth="100dp"
android:gravity="center"
android:numColumns="4"
android:scrollbars="none"
android:stretchMode="columnWidth" >
</GridView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="@+id/feedback"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" />
</LinearLayout>
I have found a solution that is working for me. I have seen a couple of same questions about this kind of issues without answers because of that I will answer my own question so maybe it can help those who have this kind of issues. I made custom button class with different attrs called Bg_button:
public class Bg_button extends Button {
private static final int[] STATE_C = {R.attr.state_chosen};
private static final int[] STATE_R = {R.attr.state_right};
private static final int[] STATE_W = {R.attr.state_wrong};
public boolean mIschosen = false;
public boolean mIsright = false;
public boolean mIswrong = false;
public Bg_button(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 3);
if (mIschosen) {
mergeDrawableStates(drawableState, STATE_C);
}
if (mIsright) {
mergeDrawableStates(drawableState, STATE_R);
}
if (mIswrong) {
mergeDrawableStates(drawableState, STATE_W);
}
return drawableState;
}
public void setchosen(boolean ischosen) {mIschosen = ischosen;
refreshDrawableState();}
public void setright(boolean isright) {mIsright = isright;
refreshDrawableState();}
public boolean setwrong(boolean iswrong) {mIswrong = iswrong;
refreshDrawableState();
return true;}
@Override
public void getHitRect(Rect outRect) {
outRect.set(getLeft() + 20, getTop() + 20, getRight() - 20, getBottom() - 20);
}
}
So the solution I have found is limiting the touch area of the button so they do not intercept. I don't know how ethical this is but it is working for me now.
@Override
public void getHitRect(Rect outRect) {
outRect.set(getLeft() + 20, getTop() + 20, getRight() - 20, getBottom() - 20);
}
}
This is the best answer I can come up with so far. I limited the touch area of button to its center with reversing the transaction that we do for expanding it. And the 3 lines code above did the trick. I hope this helps.