Ik wil fling
gebaren detectie werkend krijgen in mijn Android applicatie.
Wat ik heb is een GridLayout
dat 9 `ImageView``s bevat. De bron kan hier gevonden worden: [Romain Guys's Grid Layout][4].
Dat bestand dat ik neem is van Romain Guy's Photostream application en is slechts licht aangepast.
Voor de eenvoudige klik situatie hoef ik alleen maar de onClickListener
voor elke ImageView
die ik toevoeg in te stellen als de hoofd activity
die View.OnClickListener
implementeert. Het lijkt oneindig veel ingewikkelder om iets te implementeren dat een fling
herkent. Ik neem aan dat dit is omdat het views
kan overspannen?
Als mijn activiteit implementeert
OnGestureListener
implementeert, weet ik niet hoe ik
instellen als de gebaren luisteraar voor
de Grid
of de Image
views die ik
toevoeg.
public class SelectFilterActivity extends Activity implementeert
View.OnClickListener, OnGestureListener { ...
Als mijn activiteit implementeert
OnTouchListener
implementeert dan heb ik geen
onFling
methode te overriden
(het heeft
twee gebeurtenissen als parameters waardoor ik
om te bepalen of de worp
opmerkelijk was).
public class SelectFilterActivity extends Activity implements
View.OnClickListener, OnTouchListener { ...
Als ik een aangepaste View
maak, zoals GestureImageView
die ImageView
uitbreidt, weet ik niet hoe ik de activiteit moet vertellen dat er een fling
is opgetreden vanuit de view. In ieder geval, ik heb dit geprobeerd en de methodes werden'niet aangeroepen als ik het scherm aanraakte.
Ik heb echt alleen een concreet voorbeeld nodig van hoe dit werkt over views heen. Wat, wanneer en hoe moet ik deze listener
koppelen? Ik moet ook enkele klikken kunnen detecteren.
// Gesture detection
mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
int dx = (int) (e2.getX() - e1.getX());
// don't accept the fling if it's too short
// as it may conflict with a button push
if (Math.abs(dx) > MAJOR_MOVE && Math.abs(velocityX) > Math.absvelocityY)) {
if (velocityX > 0) {
moveRight();
} else {
moveLeft();
}
return true;
} else {
return false;
}
}
});
Is het mogelijk om een transparante view over de bovenkant van mijn scherm te leggen om flings op te vangen?
Als ik ervoor kies om mijn kind-afbeeldingen niet te inflate
vanuit XML, kan ik dan de GestureDetector
doorgeven als constructor parameter aan een nieuwe subklasse van ImageView
die ik aanmaak?
Dit is de zeer eenvoudige activiteit die ik probeer om de fling
detectie te laten werken: SelectFilterActivity (Aangepast van photostream).
Ik'heb naar deze bronnen gekeken:
Niets heeft tot nu toe voor mij gewerkt en ik hoopte op wat tips.
Met dank aan Code Shogun, wiens code ik aan mijn situatie heb aangepast.
Laat uw activiteit OnClickListener
zoals gewoonlijk implementeren:
public class SelectFilterActivity extends Activity implements OnClickListener {
private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
private GestureDetector gestureDetector;
View.OnTouchListener gestureListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* ... */
// Gesture detection
gestureDetector = new GestureDetector(this, new MyGestureDetector());
gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
};
}
class MyGestureDetector extends SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
try {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
// right to left swipe
if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
Toast.makeText(SelectFilterActivity.this, "Left Swipe", Toast.LENGTH_SHORT).show();
} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
Toast.makeText(SelectFilterActivity.this, "Right Swipe", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
// nothing
}
return false;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
}
}
Maak je gebaren-luisteraar vast aan alle views die je toevoegt aan de hoofdlayout;
// Do this for each view added to the grid
imageView.setOnClickListener(SelectFilterActivity.this);
imageView.setOnTouchListener(gestureListener);
Kijk vol ontzag toe hoe je overridden methods geraakt worden, zowel de onClick(View v)
van de activity als de onFling
van de gesture listener.
public void onClick(View v) {
Filter f = (Filter) v.getTag();
FilterFullscreenActivity.show(this, input, f);
}
De post 'fling' dans is optioneel maar wordt aangemoedigd.
De bovenstaande veegbewegingen detector code is erg nuttig! Je kunt deze oplossing echter dichtheids agnostisch maken door de volgende relatieve waarden (REL_SWIPE)
te gebruiken in plaats van de absolute waarden (SWIPE_)
DisplayMetrics dm = getResources().getDisplayMetrics();
int REL_SWIPE_MIN_DISTANCE = (int)(SWIPE_MIN_DISTANCE * dm.densityDpi / 160.0f);
int REL_SWIPE_MAX_OFF_PATH = (int)(SWIPE_MAX_OFF_PATH * dm.densityDpi / 160.0f);
int REL_SWIPE_THRESHOLD_VELOCITY = (int)(SWIPE_THRESHOLD_VELOCITY * dm.densityDpi / 160.0f);
Ook als een kleine verbetering.
De belangrijkste reden voor het try/catch blok is dat e1 null zou kunnen zijn voor de initiële beweging. in aanvulling op de try/catch, voeg een test voor null en return toe. vergelijkbaar met het volgende
if (e1 == null || e2 == null) return false;
try {
...
} catch (Exception e) {}
return false;