Androidアプリがあります。ただし、1つのフラグメントビューから別のビューに移動するには、スワイプの方向を知っている必要がある新しい機能を追加する必要があります。 (つまり、左にスワイプすると1つのことを行い、右にスワイプすると別のことを行います)。
スワイプが終わった後でイベントが発生する必要はないことに注意してください。スワイプが発生したときに、これらのイベントを実行する必要があります。 setOnPageChangeListener()
の使用を考えましたが、スワイプの方向がわかりません。スワイプの方向を理解する方法について教えてください。
ありがとう。
私はこの問題に遭遇し、特定の方向へのスワイプを防ぐために、スワイプの方向を知る必要がありますそれが起こっていたように。これが私が私の問題をどのように解決したかです、うまくいけば誰かに役立つでしょう。以前の例はすべて、私が必要としているものに対して非効率的であることがわかりました。
ViewPagerをサブクラス化する場合、ViewPager
のonInterceptTouchEvent(MotionEvent event)
およびonTouchEvent(MotionEvent event)
メソッドに応答できます。
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
boolean wasSwipeToRight = this.wasSwipeToRightEvent(event));
// Do what you want here with left/right swipe
return super.onInterceptTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean wasSwipeToRight = this.wasSwipeToRightEvent(event));
// Do what you want here with left/right swipe
return super.onTouchEvent(event);
}
以下は、イベントの方向を決定するために呼び出されるメソッドです。
// Stores the starting X position of the ACTION_DOWN event
float downX;
/**
* Checks the X position value of the event and compares it to
* previous MotionEvents. Returns a true/false value based on if the
* event was an swipe to the right or a swipe to the left.
*
* @param event - Motion Event triggered by the ViewPager
* @return - True if the swipe was from left to right. False otherwise
*/
private boolean wasSwipeToRightEvent(MotionEvent event){
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
return false;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
return downX - event.getX() > 0;
default:
return false;
}
}
ViewPager.OnPageChangeListener のonPageSelected(int position)
メソッドを見てください。 position
は、新しく選択されたページのインデックスを提供します。現在のページインデックスを追跡している場合は、それをposition
インデックスと比較して、スワイプの左/右方向を取得できます。
OnPageChangeListenerは役に立たないと述べたので、ViewPager
のonInterceptTouchEvent (MotionEvent ev)
メソッドを検討してください。 MotionEventのACTION_DOWN、ACTION_MOVE、ACTION_UPを考慮してください。お役に立てれば。
これは、現在のページを追跡するためにインスタンス変数を導入するだけで十分簡単です。
public class MyActivity extends Activity implements ViewPager.OnPageChangeListener {
private ViewPager viewPager;
private int currentPosition;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Do trivial stuff
.
.
.
viewPager.setOnClickListener(this); // doesnt have to be in onCreate
}
@Override
public void onPageSelected(int position) {
if(currentPosition < position) {
// handle swipe LEFT
} else if(currentPosition > position){
// handle swipe RIGHT
}
currentPosition = position; // Update current position
}
}
多分あなたはこのようなリスナーを構築することができます:
buttonIcons.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(final View v, final MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
return true;
case MotionEvent.ACTION_UP:
upX = event.getX();
final float deltaX = downX - upX;
if (deltaX > 0 && deltaX > SWIPE_MIN_DISTANCE) {
final Animation loadInAnimation = AnimationUtils
.loadAnimation(
activity.this,
R.anim.slide_in_right);
final Animation loadOutAnimation = AnimationUtils
.loadAnimation(
activity.this,
R.anim.slide_out_left);
viewFlipper.setInAnimation(loadInAnimation);
viewFlipper.setOutAnimation(loadOutAnimation);
viewFlipper.showPrevious();
startSaveButtonAnimation();
}
if (deltaX < 0 && -deltaX > SWIPE_MIN_DISTANCE) {
final Animation loadInAnimation = AnimationUtils
.loadAnimation(
activity.this,
R.anim.slide_in_left);
final Animation loadOutAnimation = AnimationUtils
.loadAnimation(
activity.this,
R.anim.slide_out_right);
viewFlipper.setInAnimation(loadInAnimation);
viewFlipper.setOutAnimation(loadOutAnimation);
viewFlipper.showNext();
startSaveButtonAnimation();
}
return true;
}
return false;
}
});
実際には、onPageScrolled
のパラメーターを使用して方向を見つけることができます。
次のリスナーは、ネットフラグメントの変更方向ごとに1回ログメッセージを表示するように設定されています(左のフラグメントが表示される場合は左、フラグメントが表示されない場合は中央、右のフラグメントが表示される場合は右)。
クラス変数、追跡する必要がある
// -1 - left, 0 - center, 1 - right
private int scroll = 0;
// set only on `onPageSelected` use it in `onPageScrolled`
// if currentPage < page - we swipe from left to right
// if currentPage == page - we swipe from right to left or centered
private int currentPage = 0;
// if currentPage < page offset goes from `screen width` to `0`
// as you reveal right fragment.
// if currentPage == page , offset goes from `0` to `screen width`
// as you reveal right fragment
// You can use it to see
//if user continue to reveal next fragment or moves it back
private int currentOffset = 0;
// behaves similar to offset in range `[0..1)`
private float currentScale = 0;
リスナー
pager.addOnPageChangeListener(
new OnPageChangeListener(){
@Override
public void onPageScrolled(int page, float scale, int offset){
if(scale != 0f && offset > 10){
if(currentOffset > offset && currentScale > scale && (page + 1) == currentPage){
if(scroll != -1){
newImageSet = true;
scroll = -1;
Log.e("scroll", "left");
}
} else if(currentOffset < offset && currentScale < scale && page == currentPage){
if(scroll != 1){
newImageSet = true;
scroll = 1;
Log.e("scroll", "right");
}
}
currentOffset = offset;
currentScale = scale;
}
@Override
public void onPageSelected(int i){
Log.e("scroll","centre");
// we are centerd, reset class variables
currentPage = i;
currentScale = 0;
currentOffset = 0;
scroll = 0;
}
@Override
public void onPageScrollStateChanged(int i){
}
}
);
OnPageChangeListnerをViewPagerに追加して、次のようにすることができます。
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
float tempPositionOffset = 0;
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (position == 0) {
if (tempPositionOffset < positionOffset) {
Log.d("eric", "scrolling left ...");
} else {
Log.d("eric", "scrolling right ...");
}
tempPositionOffset = positionOffset;
Log.d("eric", "position " + position + "; " + " positionOffset " + positionOffset + "; " + " positionOffsetPixels " + positionOffsetPixels + ";");
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
この小さな実装を使用して、ユーザーがスクロール中に右または左にスクロールしているかどうかを検出します。私が気付いていない特定の条件の間にいくつかのバグがあるかもしれませんが、それは私がタッチリスナーを追加する必要なしに必要なものを思いつくことができるものです:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
int SCROLLING_RIGHT = 0;
int SCROLLING_LEFT = 1;
int SCROLLING_UNDETERMINED = 2;
int currentScrollDirection = 2;
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (isScrollDirectionUndetermined()){
setScrollingDirection(positionOffset);
}
if (isScrollingLeft()){
Log.i("TabLayout","Scrolling LEFT");
}
if (isScrollingRight()){
Log.i("TabLayout","Scrolling RIGHT");
}
}
private void setScrollingDirection(float positionOffset){
if ((1-positionOffset)>= 0.5){
this.currentScrollDirection = SCROLLING_RIGHT;
}
else if ((1-positionOffset)<= 0.5){
this.currentScrollDirection = SCROLLING_LEFT;
}
}
private boolean isScrollDirectionUndetermined(){
return currentScrollDirection == SCROLLING_UNDETERMINED;
}
private boolean isScrollingRight(){
return currentScrollDirection == SCROLLING_RIGHT;
}
private boolean isScrollingLeft(){
return currentScrollDirection == SCROLLING_LEFT;
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE){
this.currentScrollDirection = SCROLLING_UNDETERMINED;
}
}
});
ユーザーが左から右にスクロールしているときはpositionOffset
が0-> 1になり、右から左にスクロールしているときは1-> 0になるため、スクロール方向を検出できます。その後、その値を確認できますスクロールの最初に1回、スクロールの最後にのみフラグをリセットします。
currentScrollDirection
をonPageSelected
ではなくアイドル位置で不定に設定します。これは、ユーザーがスクロールの途中で離すとonPageSelected
が呼び出され、誤った読み取りが行われるためです。 。