问题
DISCLAIMER: I am aware that this post may be long compared to others, but I honestly could not find any post in SO that was helpful (recommended links welcome!), and I also could not find any other way to break this problem down any simpler... That said, I would greatly appreciate it if you could help me out as I have been stuck on this issue for quite awhile now...
For an array of String values in GridView (Linear Layout - vertical), I implemented the OnSwipeTouchListener class for swiping in each direction and it worked throughout the whole screen as the according Toast messages popped up...
The following green circle shows that the whole screen outputs Toast messages for each swipe direction accurately:
But why is that when I try the same thing with an array of Button objects (for the sake of applying backgrounds for each String value) in GridView, it's only accurate for the bottom side of the layout?
The following red circle implies that the swipe directions are either only up or null objects as this is the inaccurate side, whereas the green circle implies the opposite as every swipe direction is accurate on the bottom third of the screen:
As for my Java code, here's my MainActivity:
package dpark.sample;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.Toast;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private int height, width;
private String[] list;
private GridView grid;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
height = 6;
width = 6;
grid = (GridView)findViewById(R.id.gridview);
grid.setNumColumns(width);
buildList();
display();
//*** COMMENTED OUT AS THE FOLLOWING STATEMENTS ARE USED FOR JUST STRING VALUES ***
/*ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, list);
grid.setAdapter(adapter);*/
grid.setOnTouchListener(new OnSwipeTouchListener(MainActivity.this) {
public void onSwipeTop() {
Toast.makeText(MainActivity.this, "top", Toast.LENGTH_SHORT).show();
}
public void onSwipeRight() {
Toast.makeText(MainActivity.this, "right", Toast.LENGTH_SHORT).show();
}
public void onSwipeLeft() {
Toast.makeText(MainActivity.this, "left", Toast.LENGTH_SHORT).show();
}
public void onSwipeBottom() {
Toast.makeText(MainActivity.this, "bottom", Toast.LENGTH_SHORT).show();
}
});
}
private void buildList() {
int tempIncrementor = 1;
int dimensions = height * width;
list = new String[dimensions];
for (int i = 0; i < dimensions; i++) {
list[i] = String.valueOf(tempIncrementor);
tempIncrementor++;
}
}
private void display() {
Button cb = null;
ArrayList<Button> mButtons = new ArrayList<Button>();
for (int i =0; i < list.length; i++) {
cb = new Button(this);
cb.setText(list[i]);
cb.setBackgroundResource(R.drawable.brownblock);
mButtons.add(cb);
}
grid.setAdapter(new CustomAdapter(mButtons));
}
CustomAdapter for displaying the grid with Buttons:
package dpark.puzzle_15;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import java.util.ArrayList;
public class CustomAdapter extends BaseAdapter {
private ArrayList<Button> buttonArray = null;
public CustomAdapter(ArrayList<Button> b) {
buttonArray = b;
}
@Override
public int getCount() {
return buttonArray.size();
}
@Override
public Object getItem(int position) {
return (Object) buttonArray.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Button button;
if (convertView == null) {
button = buttonArray.get(position);
} else {
button = (Button) convertView;
}
return button;
}
}
Lastly, here's OnSwipeTouchListener:
package dpark.puzzle_15;
import android.content.Context;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
public class OnSwipeTouchListener implements OnTouchListener {
private final GestureDetector gestureDetector;
public OnSwipeTouchListener (Context ctx){
gestureDetector = new GestureDetector(ctx, new GestureListener());
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
}
result = true;
}
else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeBottom();
} else {
onSwipeTop();
}
}
result = true;
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
public void onSwipeTop() {
}
public void onSwipeBottom() {
}
}
Oh, and here's the XML code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold"
android:layout_gravity="center"
android:layout_margin="12dip"
android:text="GridView of Buttons Swipe Demo"/>
<GridView
android:id="@+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:focusable="true"
android:focusableInTouchMode="true"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:columnWidth="90dp"
android:stretchMode="columnWidth"
android:gravity="center"
android:layout_gravity="center"/>
</LinearLayout>
... All of that said, is there any way I could apply the swipe touch interface for a GridView of Button objects, let alone the whole screen layout?
Again, thank you so much.
来源:https://stackoverflow.com/questions/35511294/onswipetouchlistener-does-not-work-for-a-gridview-of-button-objects