I'm making a list with a linearLayout and adding TextViews depending on how many items I got in the database. Problem is that I want to be able to delete an item when I swipe left on the list. I was just wondering how to get the element (view) that you're swiping? Here's the code I got for adding a TextView.
for(int i = 0; i < nrOfTodos; i++) {
TextView v = new TextView(this);
String title = todos.get(i).getTitle();
System.out.println(title);
v.setText(title);
v.setHeight(listItemSize);
v.setAllCaps(true);
v.setTextColor(Color.parseColor("#FFD9A7"));
v.setTextSize(listItemSize/6);
v.setHorizontallyScrolling(false);
v.setMaxLines(1);
v.setEllipsize(TruncateAt.END);
v.setPadding(30, 50, 0, 0);
v.setId(i);
todoViews.add(v);
v.setOnTouchListener(new OnSwipeTouchListener(this) {
#Override
public void onSwipeLeft() {
/*
*
*
* TODO!!! NEXT PART OF MY PLAN TO WORLD DOMINATION!
*
*
*/
}
});
if(i%2 == 1) {
v.setBackgroundColor(Color.parseColor("#11FFFFFF"));
}
ll.addView(v, i);
}
and I also have this
public class OnSwipeTouchListener implements OnTouchListener {
private final GestureDetector gestureDetector;
public OnSwipeTouchListener(Context context) {
gestureDetector = new GestureDetector(context, new GestureListener());
}
public void onSwipeLeft() {
}
public void onSwipeRight() {
}
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_DISTANCE_THRESHOLD = 50;
private static final int SWIPE_VELOCITY_THRESHOLD = 10;
#Override
public boolean onDown(MotionEvent e) {
//always return true since all gestures always begin with onDown and <br>
//if this returns false, the framework won't try to pick up onFling for example.
return true;
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
float distanceX = e2.getX() - e1.getX();
float distanceY = e2.getY() - e1.getY();
if (Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (distanceX > 0)
onSwipeRight();
else
onSwipeLeft();
return true;
}
return false;
}
}
}
but I can't figure out how to actually get the view, get the titletext and remove that from the database (I can remove from the database, but I can't get what item was swiped ^^).
Any ideas would be greatly appreciated.
You may refer to this sample application Swipe_To_Delete
You may use ListView to list your data items which are got from the db.
Then modify the getSwipeItem() method in the MainActivity of the example, as follows.
#Override
public void getSwipeItem(boolean isRight, int position) {
[List_Of_Items].remove(position);
[Your_Adapter].notifyDataSetChanged();
}
Related
I had a recyclerview with an adapter and everything was cool. I added view.setOnTouchListener so that I could scroll this recyclerview along with animation and other elements on 1 screen from left to right. But after that, scrolling up and down broke in recyclerview, and onclicklistener on the elements inside it stopped working. What to do and how to fix this conflict?
At the moment I can put return false in the public boolean onTouch (View v, MotionEvent event) method; instead of return gestureDetector.onTouchEvent (event); and get a working scrolling up and down back, but left-right stops working. I can do simultaneous scrolling as in ios, when scrolling of tablecloths and collections did not break when adding the svayp to the left-right.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
view.setOnTouchListener(new OnSwipeTouchListener(MainActivity.this) {
public void onSwipeRight() {
choseold = chosenow;
chosenow = chosenow - 1;
if (chosenow <= 0) {
chosenow = 5;
choseold = 6;
}
swipe();
}
public void onSwipeLeft() {
choseold = chosenow;
chosenow = chosenow + 1;
if (chosenow >= 6) {
chosenow = 1;
choseold = 0;
}
swipe();
}
});
view.setFocusableInTouchMode(true);
MyAdapterlang = new MyAdapterLang(MainActivity.this, yaziki1, yaziki2, flagi);
RVlang.setAdapter(MyAdapterlang);
mLayoutManager = new LinearLayoutManager(this);
RV1.setLayoutManager(mLayoutManager);
MyAdapter = new MyAdapterApps(MainActivity.this, childs, childs2);
RV1.setAdapter(MyAdapter);
}
}
class OnSwipeTouchListener implements View.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);
//return false;
}
/*public boolean onTouch(final View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
y1 = event.getY();
break;
case MotionEvent.ACTION_MOVE:
y2 = event.getY();
float deltaY = y2 - y1;
if (Math.abs(deltaY) > MIN_DISTANCE) {
return false;
} else {
return gestureDetector.onTouchEvent(event);
}
}
return gestureDetector.onTouchEvent(event);
}
private float y1, y2;
private static final int MIN_DISTANCE = 50;*/
private final class GestureListener extends GestureDetector.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) {
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();
}
return true;
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
return false;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
}
Here in ios, for example, is very simple and does not break the scrolling of collections:
- (void)viewDidLoad {
UISwipeGestureRecognizer * swipeleft=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(swipeleft:)];
swipeleft.direction=UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:swipeleft];
UISwipeGestureRecognizer * swiperight=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(swiperight:)];
swiperight.direction=UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:swiperight];
}
-(void)swipeleft:(UISwipeGestureRecognizer*)gestureRecognizer
{
if (self.currentnew <= 3) {
self.whatpress = 1;
[self.buttonnew sendActionsForControlEvents:UIControlEventTouchUpInside];
}
}
-(void)swiperight:(UISwipeGestureRecognizer*)gestureRecognizer
{
if ((self.currentnew >= 1) && (self.currentnew <= 3)) {
self.whatpress = 2;
[self.buttonnew sendActionsForControlEvents:UIControlEventTouchUpInside];
}
}
Here is a video:
https://2ch.hk/pr/src/1314926/15464190246250.mp4 https://2ch.hk/pr/src/1314926/15464193253190.mp4
If you only want to hook into default touch handling implementation you must return false here
#Override
public boolean onTouch(View v, MotionEvent event) {
gestureDetector.onTouchEvent(event);//Idk if it is needed or not - out of scope
return false;
}
Otherwise touch event will be considered as consumed and wont be propagated to other handlers (that handles scrolling, clicking etc. - all that stuff that stops working for you)
Im making an android game that only needs to recognize swipes. However, the onFling method is never called for some reason. I have no issue with modifying onScroll or other methods just so that onFling works. The GestureDetectGridView is just a basic class that calls the gridView super constructor. The Movement Controller is definitely correct as well. So the issue has to be in this class.
public class TwentyGestureDetectGridView extends GestureDetectGridView implements View.OnTouchListener, GestureDetector.OnGestureListener {
private static final int SWIPE_MIN_DISTANCE = 100;
private final GestureDetector gDetector;
private TwentyMovementController mController;
public TwentyGestureDetectGridView(Context context) {
super(context);
gDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener());
mController = new TwentyMovementController();
}
public TwentyGestureDetectGridView(Context context, AttributeSet attrs) {
super(context, attrs);
gDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener());
mController = new TwentyMovementController();
}
public TwentyGestureDetectGridView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
gDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener());
mController = new TwentyMovementController();
}
public void onSwipeUp(){}
public void onSwipeDown(){}
public void onSwipeLeft() {}
public void onSwipeRight() {}
public boolean onTouch(View v, MotionEvent event) {
return gDetector.onTouchEvent(event);
}
#Override
public boolean onDown(MotionEvent e) {
return true;
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
float distanceX = e2.getX() - e1.getX();
float distanceY = e2.getY() - e1.getY();
if (Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(distanceX) > SWIPE_MIN_DISTANCE) {
if (distanceX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
return true;
} else if (Math.abs(distanceY) > Math.abs(distanceX) && Math.abs(distanceY) > SWIPE_MIN_DISTANCE) {
if (distanceY > 0) {
onSwipeUp();
} else {
onSwipeDown();
}
return true;
}
return false;
}
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {return true;}
You are missing a call to View.setOnTouchListener
For the view you want to register swipes in (probably your base layout), call view.setOnTouchListener(your listener here)
Maybe like this:
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstance){
View root = somehowCreateView();
root.setOnTouchListener(this);
return root;
}
public class TwentyGameActivity extends GameActivity implements Observer {
TwentyBoardManager twentyBoardManager;
private TwentyGestureDetectGridView gridView;
private static int columnWidth, columnHeight;
ArrayList<Button> tileButtons;
public void display() {
updateTileButtons();
gridView.setAdapter(new CustomAdapter(tileButtons, columnWidth, columnHeight));
}
private void createTileButtons(Context context){
TwentyBoard board = twentyBoardManager.getBoard();
tileButtons = new ArrayList<>();
for (int row = 0; row != board.getNumRows(); row++) {
for (int col = 0; col != board.getNumCols(); col++) {
Button tmp = new Button(context);
tmp.setBackgroundResource(board.getTile(row, col).getBackground());
this.tileButtons.add(tmp);
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
twentyBoardManager = (TwentyBoardManager) Savable.loadFromFile(TEMP_SAVE_FILENAME);
createTileButtons(this);
setContentView(R.layout.activity_twenty_game);
gridView = findViewById(R.id.gridTwenty);
gridView.setNumColumns(twentyBoardManager.getSize());
gridView.setBoardManager(twentyBoardManager);
twentyBoardManager.addObserver(this);
gridView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
gridView.getViewTreeObserver().removeOnGlobalLayoutListener(
this);
int displayWidth = gridView.getMeasuredWidth();
int displayHeight = gridView.getMeasuredHeight();
columnWidth = displayWidth / twentyBoardManager.twentyBoard.getNumCols();
columnHeight = displayHeight / twentyBoardManager.twentyBoard.getNumCols();
display();
}
});
addUndoButtonListener();
twentyBoardManager.twentyBoard.generateRandomTile();
}
private void addUndoButtonListener(){
Button undoButton = findViewById(R.id.undoTwentyButton);
undoButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
twentyBoardManager.undo();
}
});
}
#Override
public void update(Observable o, Object arg) {
display();
}
private void updateTileButtons() {
TwentyBoard board = twentyBoardManager.getBoard();
int nextPos = 0;
for (Button b : tileButtons) {
int row = nextPos / board.getNumCols();
int col = nextPos % board.getNumCols();
b.setBackgroundResource(board.getTile(row, col).getBackground());
nextPos++;
}
}
}
I'm using GestureDetector.OnGestureListener to invoke method when user moves finger across the screen in the specified direction.
My problem - just move slightly and the method is called, I would like the user to move his finger a little more on the screen.
public class SwipeListener extends GestureDetector.SimpleOnGestureListener {
public static final int MIN_SWIPE_DISTANCE = 40;
#Override
public boolean onDown(MotionEvent e) {
return true;
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
float xDiff = e1.getX() - e2.getX();
float yDiff = e1.getY() - e2.getY();
return resolveSwipe(xDiff, yDiff);
}
private boolean resolveSwipe(float xDist, float yDist) {
float yDistAbs = Math.abs(yDist);
float xDistAbs = Math.abs(xDist);
SwipeDirection swipeDirection;
if (yDistAbs > xDistAbs) {
if (yDistAbs < MIN_SWIPE_DISTANCE) {return false;}
swipeDirection = (yDist > 0) ? SwipeDirection.DOWN: SwipeDirection.UP;
} else {
if (xDistAbs < MIN_SWIPE_DISTANCE) {return false;}
swipeDirection = (xDist > 0) ? SwipeDirection.RIGHT: SwipeDirection.LEFT;
}
onSwipeEvent(swipeDirection);
return true;
}
private void onSwipeEvent(SwipeDirection swipeDirection) {
if (swipeDirection == SwipeDirection.UP) {
return;
}
if (swipeDirection == SwipeDirection.DOWN) {
return;
}
if (swipeDirection == SwipeDirection.LEFT) {
finger1()
return;
}
if (swipeDirection == SwipeDirection.RIGHT) {
finger1();
return;
}
}
public enum SwipeDirection {
UP, DOWN, LEFT, RIGHT
}
Is it possible? What should I change or add here?
You need to calculate as to what level of x-axis or y-axis you don't want to perform any action on swipe.
You have to declare minimum distance for swipe as private static final int SWIPE_MIN_DISTANCE = 160 may be it will help you Click here to implement it
I'm a little confused by polymorphism and interfaces in Java.
Basically I want to make a class called gestureRecogniser which has the methods:
-onLeftwardsSwipe();
-onRightwardsSwipe();
-onUpwardsSwipe();
-onDownwardsSwipe();
The gestureRecogniser will call these methods as needed. A second class implements gestureRecogniser and specifies what must be done on these events. Is this possible in Java?
This is the class that I've written:
public abstract class GestureRecogniser implements OnTouchListener {
Activity activity;
private float XWherePressed;
private float XWhereReleased;
private float YWherePressed;
private float YWhereReleased;
private static final int MINIMUM_DISTANCE_FOR_SWIPE = 100;
public GestureRecogniser(Activity activity)
{
this.activity = activity;
}
public abstract void onLeftwardsSwipe();
public abstract void onRightwardsSwipe();
public abstract void onUpwardsSwipe();
public abstract void onDownwardsSwipe();
public boolean onTouch(View v, MotionEvent event)
{
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
this.XWherePressed = event.getX();
this.YWherePressed = event.getY();
break;
case MotionEvent.ACTION_UP:
this.XWhereReleased = event.getX();
this.YWhereReleased = event.getY();
float deltaX = XWhereReleased - XWherePressed;
float deltaY = YWhereReleased - YWherePressed;
if (Math.abs( deltaX ) > this.MINIMUM_DISTANCE_FOR_SWIPE)
{
//HORIZONTAL SWIPE
if(deltaX > 0 )
{
this.onRightwardsSwipe();
return true;
}
if(deltaX < 0)
{
this.onLeftwardsSwipe();
return true;
}
}else return false;
if (Math.abs( deltaY) > this.MINIMUM_DISTANCE_FOR_SWIPE)
{
//VERTICAL SWIPE
if( deltaY < 0 )
{
this.onDownwardsSwipe();
return true;
}
if ( deltaY > 0 )
{
this.onUpwardsSwipe();
return true;
}
}else return false;
break;
}
return false;
}
}
I managed to achieve the desired result by doing the following:
1 - Create a public interface with the methods:
public interface OnSwipeListener
{
public void onUpwardsSwipe();
public void onDownwardsSwipe();
public void onLeftwardsSwipe();
public void onRightwardsSwipe();
}
2 - Create a class that implements onTouchListener. The class' constructor takes an OnSwipeListener object. The onTouch() method calls the methods as needed:
public class SwipeRecogniser implements OnTouchListener {
private OnSwipeListener onSwipeListener;
private float XWherePressed;
private float XWhereReleased;
private float YWherePressed;
private float YWhereReleased;
private static final int MINIMUM_DISTANCE_FOR_SWIPE = 100;
public SwipeRecogniser(OnSwipeListener onSwipeListener)
{
this.onSwipeListener = onSwipeListener;
}
public boolean onTouch(View v, MotionEvent event)
{
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
this.XWherePressed = event.getX();
this.YWherePressed = event.getY();
break;
case MotionEvent.ACTION_UP:
this.XWhereReleased = event.getX();
this.YWhereReleased = event.getY();
float deltaX = XWhereReleased - XWherePressed;
float deltaY = YWhereReleased - YWherePressed;
if (Math.abs( deltaX ) > this.MINIMUM_DISTANCE_FOR_SWIPE)
{
//HORIZONTAL SWIPE
if(deltaX > 0 )
{
onSwipeListener.onRightwardsSwipe();
return true;
}
if(deltaX < 0)
{
onSwipeListener.onLeftwardsSwipe();
return true;
}
}
else return true;
if (Math.abs( deltaY) > this.MINIMUM_DISTANCE_FOR_SWIPE)
{
//VERTICAL SWIPE
if( deltaY < 0 )
{
onSwipeListener.onDownwardsSwipe();
return true;
}
if ( deltaY > 0 )
{
onSwipeListener.onUpwardsSwipe();
return true;
}
}
else return true;
break;
}
return true;
}
}
3 - In the custom class
public class MyClass extends Activity implements OnSwipeListener
{
protected void onCreate(Bundle stuff)
{
//
this.setOnTouchListener(new SwipeRecogniser(this));
}
public void onUpwardsSwipe(){/*methods*/}
public void onDownwardsSwipe(){/*methods*/}
public void onLeftwardsSwipe(){/*methods*/}
public void onRightwardsSwipe(){/*methods*/}
}
//Declare below inner class
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) {
////swapped left
}
else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
////swapped right
}
} catch (Exception e) {
// nothing
}
return false;
}
}
//in your activtiy do below stuff and override onTouchEvent
private static final int SWIPE_MIN_DISTANCE = 50;
private static final int SWIPE_MAX_OFF_PATH = 400;
private static final int SWIPE_THRESHOLD_VELOCITY = 250;
private GestureDetector gestureDetector;
View.OnTouchListener gestureListener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Do your stuff
gestureDetector = new GestureDetector(new MyGestureDetector());
gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (gestureDetector.onTouchEvent(event)) {
return true;
}
return false;
}
};
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (gestureDetector.onTouchEvent(event))
return true;
else
return false;
}
I would like to have a OnTouchListener for the entire screen. I've tried attaching all views to an onTouchListener but generates bad touchEvents. I know this can be achived by overriding methods, what i am looking for is a listener solution. Thanks!
Can this be done using a gesture listener?
You can insert a onSwipeListener class with methods that listen to the swipe action. You can then set view.OnTouchListener for the layout of the activity(LinearLayout/RelativeLayout) and then override the various methods of the onSwipeListener and insert the various tasks.
Below is the onSwipeListener class that you can create.
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() {
}
}
After creating this class, you can call it as follows:
relativeLayout.setOnTouchListener(new OnSwipeTouchListener(context) {
public void onSwipeRight() {
//do something
}
public void onSwipeLeft() {
//do something
}
}
Hope this helps!