i'm using viewpagerIndicator in my app, i have 200 pages. is possible disable the Swipe 1 page before the last page?
Example my currentpage is the 199 here the swipe is disble and never change to the next page, only the previous pages.
EDIT: i have one calendar in the Tabindicator, the pages show info for day, i need show the next day but not swipe because not exist info for this reason i need disable this page.
Exam:
19/ago/2014 | 20/ago/2014 | 21/ago/2014
before |Current |Last Page
in before i can swipe left and right but in Current i need only swipe left and disable right is possible?
You can return 199 from getCount() from adapter that way viewpager will not know there are 200 pages.
EDIT:
Well In that case, you have to override viewpager and manually disable the motion when viewpager is showing second last page.
It would look something like this
First extend : class CustomViewPager extends ViewPager {...}
float lastX;
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if(getCurrentItem() == getAdapter().getCount()-1){
if(ev.getAction() == MotionEvent.ACTION_DOWN){
lastX = ev.getX();
// Just touch down let viewpager also handle touch event
return super.onInterceptTouchEvent(event);
}
else if(ev.getAction() == MotionEvent.ACTION_MOVE){
float xDiff = ev.getX() - lastX;
if(xDiff > 0){
// Attempt to move right on second last page
// Return false, we dont want to handle this movement
return false;
}
else{
// Left you can move
return super.onInterceptTouchEvent(event);
}
}
// Notice that we are not updating lastX on motion towards left
// This is to enable user can swipe towards left a bit and comeback, but dont dare go right
}
else{
// Not on second last page let viewpager handle page event
return super.onInterceptTouchEvent(event);
}
}
Related
I'm making video stories like instagram. So I met a problem with gestures.
The problem is that ACTION_CANCEL handled when I'm doing these moves and ACTION_UP doesn't call if I raise my finger
I'm in 1st page of ViewPager and I swipe left->right fastly (my finger still on screen)
I'm in the middle of ViewPager and I swipe left->right or right->left, but not finishing the swipe and I'm still in the current page and my finger on screen
I'm moving chaosly on screen (my finger still on screen)
So if I raise my finger after ACTION_CANCEL called, my video stay in "PAUSE" state
Finally, question is: How I can handle Action_Up event after Action_Cancel?
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
if (gestureDetector?.onTouchEvent(event) == true) return true
when (event?.actionMasked) {
MotionEvent.ACTION_DOWN -> {
viewModel.videoPause()
}
MotionEvent.ACTION_UP -> {
viewModel.videoResume()
}
MotionEvent.ACTION_CANCEL -> {
// Handles when doing these moves and ACTION_UP doesn't call if I raise my finger
// 1. I'm in 1st page of ViewPager and I swipe left->right fastly (my finger still on screen)
// 2. I'm in the middle of ViewPager and I swipe left->right or right->left, but not finishing the swipe
// and I'm still in the current page and my finger on screen
// 3. I'm moving chaosly on screen (my finger still on screen)
// So if I raise my finger after ACTION_CANCEL called, my video stay in "PAUSE" state
}
else -> { }
}
return true
}
You don't get an ACTION_UP after an ACTION_CANCEL:
ACTION_CANCEL
public static final int ACTION_CANCEL
Constant for getActionMasked(): The current gesture has been aborted. You will not receive any more points in it. You should treat this as an up event, but not perform any action that you normally would.
Actually there is a way to do this.
#Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
performClick();
switch (event.getAction()){
case MotionEvent.ACTION_MOVE:
float x = event.getX();
float y = event.getY();
Log.d("coordinates: ","x : "+String.valueOf(x)+"y : " + String.valueOf(y));
break;
case MotionEvent.ACTION_UP:
Log.d("action","up")
}
return true;
}
Add this to your parent View. This will show you the location of your finger whenever it moves. And (I don't know how) but when you hold your finger, it also triggers the action up. So whenever the action up is triggered, you'll know that the user held his finger, or whenever the x or y coordinates are outside of your parent view, you can treat it as if the user held his finger. (I got this idea from a canvas question [https://stackoverflow.com/questions/21846584/android-canvas-draw-by-finger])
I have a list view and I want to make it so I can swipe each item to reveal a delete button:
I've figured out how to recognise the swipe event, I am using this code (listItem is of type View):
listItem.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
_xSwipe1 = event.getX();
break;
case MotionEvent.ACTION_UP:
_xSwipe2 = event.getX();
float deltaX = _xSwipe2 - _xSwipe1;
if (deltaX < 0)
{
Log.e("SWIPE", "Right to Left swipe");
}
else if (deltaX >0)
{
Log.e("SWIPE", "Left to right swipe");
}
break;
}
return false;
}
});
And when I swipe, I can see in the logs that the swipe event is being recognised.
However, I'm not sure how to physically make the list item start disappearing to the left?
Any help would be greatly appreciated.
If you know when the swipe is happening and how much the user has swiped you could call View.setTranslationX() depending on how much the user has swiped. Alternatively, you could forego the swipe detection logic altogether and use a ViewPager with only 2 pages. You would then override PagerAdapter.getPageWidth(...) in your PagerAdapter so that the delete button only takes up a limited amount of space.
Solution-1: By specifying a very large number as the actual count, but maps them to the actual range of the dataset/pageset
ViewPager as a circular queue / wrapping
Problem: It doesn't work if there are less than 4 items.
Solution-2 Adding 2 extra items i.e. last item in the first and first item in the last and onPageSelected, depending on the position values, set the current item
Implementing Circular Scrolling In PagerAdapter
Problem: Extra pager indicators and extra fragment instances.
Solution-3: Using the onTouchListener on ViewPager
Implementing Circular Scrolling In PagerAdapter
Problem: The first MotionEvent is always null. Is it because of the ViewPager's own onTouchListener implementation?
Is there a proper solution for this?
Or even if the 3rd solution works fine, it would be great.
I use a combination of Solution 2 and Solution 3, I use the on touch listener of the pager to watch for swipes and see if I need to show the copy of the first or last page based on the current page
example:
mPager.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
dxInitial=event.getX();
//
}else if(event.getAction() == MotionEvent.ACTION_MOVE){
//
if(event.getX() - dxInitial > 50 && currentPage==1){
}else if(dxInitial - event.getX() > 50 && currentPage==5){
mPager.setCurrentItem(0,false);
}else if(dxInitial - event.getX() > 50 && currentPage==6){
mPager.setCurrentItem(1,false);
}else if(event.getX() - dxInitial > 50 && currentPage==0){
mPager.setCurrentItem(5,false);
}else if(event.getX() - dxInitial > 100 && currentPage==6){
//
mPager.setCurrentItem(1,false);
}
}
return false;
}
});
you have extra pager indicators but the user should never see or notice them, just set smoothScroll to false when you change the page
I have a ViewPager of images, and I want to make it slide in the following way:
If I click on the right (left) side of the screen, go to previous (next) image. It's like the screen is two halves and each half moves to a direction on click.
How can I implement this?
You can get Disaplay width
Then you can override onTouchEvent in your viewpager.
When you get MotionEvent object - you can get 'tap' coordinates and you will be able to understand on wich side of screen user clicked and handle it.
Set on touch listener for your ViewPager or contentview of ViewPager item.
Take the half of the screen/view width, check if event.getX() is greater than the half value, if so, go to next, otherwise to the previous.
#Override
public boolean onTouch(View v, MotionEvent ev) {
if(ev.getAction() == MotionEvent.ACTION_DOWN){
mDownX = ev.getX();
mDownY = ev.getY();
isOnClick = true;
}else if(ev.getAction() == MotionEvent.ACTION_UP ){
if (isOnClick ) {
if(ev.getX() > mViewPager.getWidth()/2) {
//go to next
}else{
//go to previous
}
return true;
}
}else if(ev.getAction() == MotionEvent.ACTION_MOVE){
if (isOnClick && (Math.abs(mDownX - ev.getX()) > DRAG_THRESHOLD || Math.abs(mDownY - ev.getY()) > DRAG_THRESHOLD)) {
isOnClick = false;
return false;
}
}
return false
}
I have an achartengine GraphicalView chart inside a android.support.v4.view.ViewPager.
I want my chart to pan when the user drags her finger on it, but now the event is being caught by the ViewPager after a small drag movement.
Preferably, I would like to be able to let the user pan to the end of the chart and then let the ViewPager switch pages.
As an alternative, I would like to at least stop the ViewPager from catching the drag movement inside the chart.
Any ideas?
Here goes my solution.
It allows the user to drag the graph around while there is data in it. After that, the drag events are caught by the ViewPager.
Like I said, the key is this solution is the requestDisallowInterceptTouchEvent function.
public class ParameterGraphicalView extends org.achartengine.GraphicalView {
// stores the data model size
private int mDataSize = 0;
// stores the first X position in the dataset
private long mDataStartX = 0;
// stores the last X position in the dataset
private long mDataEndX = 0;
// the ViewPager
private ViewParent mViewPager;
//(...)
#Override
public boolean onTouchEvent(MotionEvent event) {
// save the position of the first touch so we can determine whether the user is dragging
// left or right
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mFirstTouchX = event.getX();
}
// when mViewPager.requestDisallowInterceptTouchEvent(true), the viewpager does not
// intercept the events, and the drag events (pan, pinch) are caught by the GraphicalView
// we want to keep the ViewPager from intercepting the event if:
// 1- there are 2 or more touches, i.e. the pinch gesture
// 2- the user is dragging to the left but there is no data to show to the right
// 3- the user is dragging to the right but there is no data to show to the left
if (event.getPointerCount() > 1
|| (event.getX() < mFirstTouchX && mDataSize > 0 && mRenderer.getXAxisMax() < mDataEndX)
|| (event.getX() > mFirstTouchX && mData.size() > 0 && mRenderer.getXAxisMin() > mDataStartX)) {
mViewPager.requestDisallowInterceptTouchEvent(true);
}
else {
mViewPager.requestDisallowInterceptTouchEvent(false);
}
return super.onTouchEvent(event);
}
}
I think you should Implement your own ViewPager and handle Touch event yourself.
Maybe this Link helps you : how to disable viewpager adapter on touching specific views?