ජාලක පිරිසැලසුම මත අභිනය හඳුනාගැනීම


1112

flingමගේ ඇන්ඩ්‍රොයිඩ් යෙදුමේ අභිනය අනාවරණය කර ගැනීමට මට අවශ්‍යය .

මා සතුව ඇත්තේ GridLayout9 ImageViews අඩංගු වේ . මූලාශ්‍රය මෙතැනින් සොයාගත හැකිය: රොමේන් ගයිස්ගේ ග්‍රිඩ් පිරිසැලසුම .

මා ගන්නා ගොනුව රොමේන් ගයිගේ ෆොටෝස්ට්‍රීම් යෙදුමෙන් වන අතර එය සුළු වශයෙන් අනුවර්තනය වී ඇත.

සරල ක්ලික් කිරීමේ අවස්ථාව සඳහා මට අවශ්‍ය වන්නේ මා එකතු onClickListenerකරන සෑම එකක්ම ක්‍රියාත්මක ImageViewකරන ප්‍රධාන දේ activityලෙස සැකසීම පමණි View.OnClickListener. හඳුනාගන්නා දෙයක් ක්‍රියාත්මක කිරීම අසීමිත ලෙස සංකීර්ණ බව පෙනේ fling. මම හිතන්නේ මෙය විහිදෙන නිසා විය viewsහැකිද?

  • මගේ ක්‍රියාකාරකම ක්‍රියාත්මක වන්නේ නම්, මම එය එකතු කරන අදහස් හෝ OnGestureListenerඅභිනය සඳහා අභිනය අසන්නා ලෙස එය සකසන්නේ කෙසේදැයි මම නොදනිමි .GridImage

    public class SelectFilterActivity extends Activity implements
       View.OnClickListener, OnGestureListener { ...
  • මගේ ක්‍රියාකාරකම් ක්‍රියාත්මක වන්නේ OnTouchListenerනම් මට ඒ සඳහා onFlingක්‍රමවේදයක් නොමැත override(එයට පරාමිතීන් ලෙස සිදුවීම් දෙකක් ඇත.

    public class SelectFilterActivity extends Activity implements
        View.OnClickListener, OnTouchListener { ...
  • මම චාරිත්රයක් කරන්නේ නම් View, GestureImageViewඑය දිගු වන පරිදි , දෘෂ්ටි කෝණයෙන් සිදු ImageViewවූ ක්රියාකාරිත්වය පවසන්නේ කෙසේදැයි මම නොදනිමි fling. කෙසේ වෙතත්, මම මෙය උත්සාහ කළ අතර මම තිරය ස්පර්ශ කරන විට ක්‍රම කැඳවනු නොලැබේ.

මට ඇත්ත වශයෙන්ම අවශ්‍ය වන්නේ අදහස් හරහා වැඩ කිරීම පිළිබඳ ස්ථිර උදාහරණයක් පමණි. මා මෙය ඇමිණිය යුත්තේ කුමක්ද, කවදාද සහ කෙසේද listener? මට තනි ක්ලික් කිරීම් හඳුනා ගැනීමට හැකි විය යුතුය.

// 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;
        }
    }
});

පියාඹා අල්ලා ගැනීම සඳහා මගේ තිරයේ ඉහළින් විනිවිද පෙනෙන දර්ශනයක් තැබිය හැකිද?

inflateඑක්ස්එම්එල් වෙතින් මගේ ළමා රූප දර්ශන නොකිරීමට මා තෝරා ගන්නේ නම්, මම නිර්මාණය GestureDetectorකරන නව උප පංතියකට ඉදිකිරීම් පරාමිතියක් ලෙස සමත් විය ImageViewහැකිද?

මෙය flingහඳුනා ගැනීම සඳහා වැඩ කිරීමට මම උත්සාහ කරන ඉතා සරල ක්‍රියාකාරකම මෙයයි : SelectFilterActivity (ඡායාරූප ප්‍රවාහයෙන් අනුවර්තනය කරන ලදි) .

මම මෙම ප්‍රභවයන් දෙස බැලුවෙමි:

මේ දක්වා කිසිවක් මා වෙනුවෙන් වැඩ කර නැති අතර මම කරුණු කිහිපයක් බලාපොරොත්තුවෙන් සිටියෙමි.


මෙම ගැටළුව විසඳන්නේ කෙසේද? කරුණාකර stackoverflow.com/questions/60464912/…
බිෂ්වාෂ්

Answers:


820

මගේ තත්වයට අනුවර්තනය කළ කේතය ෂෝගන්ට ස්තූතියි .

ඔබගේ ක්‍රියාකාරකම් OnClickListenerසුපුරුදු පරිදි ක්‍රියාත්මක කිරීමට ඉඩ දෙන්න :

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;
    }
  }
}

ප්‍රධාන පිරිසැලසුමට ඔබ එකතු කරන සියලුම අදහස් වලට ඔබේ අභිනය අසන්නා අමුණන්න;

// Do this for each view added to the grid
imageView.setOnClickListener(SelectFilterActivity.this); 
imageView.setOnTouchListener(gestureListener);

ඔබගේ අභිබවා ගිය ක්‍රමවේදයන්ට පහර දෙන onClick(View v)බැවින්, ක්‍රියාකාරිත්වයේ සහ onFlingඅභිනය අසන්නන්ගේ ක්‍රියාකාරිත්වයට බිය වන්න .

public void onClick(View v) {
  Filter f = (Filter) v.getTag();
  FilterFullscreenActivity.show(this, input, f);
}

පශ්චාත් 'පියාඹන' නැටුම විකල්ප නමුත් දිරිමත් කරනු ලැබේ.


109
මෙම කේතයට ස්තූතියි! එය ඉතා ප්‍රයෝජනවත් විය. කෙසේ වෙතත්, අභිනයන් වැඩ කිරීමට උත්සාහ කරන අතරතුර මම ඉතා කලකිරුණු එක් උඩ පන්දුවක් වෙතට දිව ගියෙමි. මගේ SimpleOnGestureListener හි, මගේ ඕනෑම අභිනය ලියාපදිංචි කිරීම සඳහා මට onDown අභිබවා යා යුතුය. එය සත්‍ය බවට පත්විය හැකි නමුත් මා අර්ථ දැක්විය යුතුය. PS: මගේ api සංශෝධනය හෝ දෘඩාංග දැයි මම නොදනිමි, නමුත් මම HTC Droid Eris හි 1.5 භාවිතා කරමි.
Cdsboy

මම ඔබේ කේතය උත්සාහ කළ අතර, මම ස්වයිප් කිරීම හෝ ක්ලික් කිරීම වැදගත් නැත (මගේ මූසිකය සමඟ, මම ඉමුලේටරයේ වැඩ කිරීමට හේතුව), මම සෑම විටම ඔන්ක්ලික් ක්‍රමයේදී නිර්වචනය කළ ටෝස්ට් එකක් ලබා ගනිමි, එම නිසා ඉමියුලේටරය හඳුනා ගන්නේ ක්ලික් කිරීම් පමණි, ස්වයිප් නොමැතිව. එය එසේ වන්නේ ඇයි?
ලොම්සා

මම මෙම කේතය උත්සාහ කළ නමුත් එය ක්‍රියාත්මක වූයේ නැත. මගේ ගැලරි දර්ශනය තුළ ළමා දර්ශන වලින් එකකට ඔන්ක්ලික් සවන්දෙන්නෙකු යොදන විට තවමත් අනුචලනය කිරීමට නොහැකි විය
ජොනතන්

අයෝම්සා: ඔබ කඩිනම් ප්‍රකාශ ඉදිරිපත් කර ඔබේ කේතය හරහා පියවර ගැනීමට උත්සාහ කළාද?
ඉගෝර්ගනාපොල්ස්කි

අභ්‍යන්තර පංතියක් භාවිතා කිරීම සඳහා ප්‍රශංසාව! ඉතා පිරිසිදු ප්රවේශයක්.
ඉගෝර්ගනාපොල්ස්කි

211

ඉහත පිළිතුරුවලින් විවිධ පික්සල් ity නත්වය හැසිරවීම ගැන සඳහන් වන නමුත් ස්වයිප් පරාමිතීන් අතින් ගණනය කිරීමට යෝජනා කරයි. ViewConfigurationපංතිය භාවිතයෙන් ඔබට සැබවින්ම පරිමාණයෙන් සාධාරණ අගයන් ලබා ගත හැකි බව සඳහන් කිරීම වටී :

final ViewConfiguration vc = ViewConfiguration.get(getContext());
final int swipeMinDistance = vc.getScaledPagingTouchSlop();
final int swipeThresholdVelocity = vc.getScaledMinimumFlingVelocity();
final int swipeMaxOffPath = vc.getScaledTouchSlop();
// (there is also vc.getScaledMaximumFlingVelocity() one could check against)

මෙම අගයන් භාවිතා කිරීමෙන් යෙදුම සහ සෙසු පද්ධතිය අතර වඩාත් අනුකූල වීමට මැස්සන්ගේ හැඟීම ඇති වන බව මම දුටුවෙමි.


11
මම භාවිතා කරමි swipeMinDistance = vc.getScaledPagingTouchSlop()සහ swipeMaxOffPath = vc.getScaledTouchSlop().
තෝමස් අහ්

8
getScaledTouchSlopමට ඉතා සුළු ඕෆ්සෙට් ප්‍රති result ලයක් ලබා දෙයි. උදාහරණයක් ලෙස 540 ඉහළ තිරයක පික්සල් 24 ක් පමණි, එය ඇඟිල්ලෙන් පරාසය තුළ තබා ගැනීම ඉතා අපහසුය. : S
WonderCsabo

148

මම එය ටිකක් වෙනස් ලෙස කරන අතර අතිරේක අනාවරක පන්තියක් ලිවීය View.onTouchListener

onCreateසරලවම එය මේ වගේ අඩුම පිරිසැලසුමට එක් කරන්න:

ActivitySwipeDetector activitySwipeDetector = new ActivitySwipeDetector(this);
lowestLayout = (RelativeLayout)this.findViewById(R.id.lowestLayout);
lowestLayout.setOnTouchListener(activitySwipeDetector);

මෙහි id.lowestLayout යනු පිරිසැලසුම් ධූරාවලියෙහි අඩුම දර්ශනය සඳහා වන id.xxx වන අතර අඩුම පිරිසැලසුම සාපේක්ෂ සැකැස්ම ලෙස ප්‍රකාශයට පත් කෙරේ

එවිට සත්‍ය ක්‍රියාකාරකම් ස්වයිප් අනාවරක පන්තිය ඇත:

public class ActivitySwipeDetector implements View.OnTouchListener {

static final String logTag = "ActivitySwipeDetector";
private Activity activity;
static final int MIN_DISTANCE = 100;
private float downX, downY, upX, upY;

public ActivitySwipeDetector(Activity activity){
    this.activity = activity;
}

public void onRightSwipe(){
    Log.i(logTag, "RightToLeftSwipe!");
    activity.doSomething();
}

public void onLeftSwipe(){
    Log.i(logTag, "LeftToRightSwipe!");
    activity.doSomething();
}

public void onDownSwipe(){
    Log.i(logTag, "onTopToBottomSwipe!");
    activity.doSomething();
}

public void onUpSwipe(){
    Log.i(logTag, "onBottomToTopSwipe!");
    activity.doSomething();
}

public boolean onTouch(View v, MotionEvent event) {
    switch(event.getAction()){
        case MotionEvent.ACTION_DOWN: {
            downX = event.getX();
            downY = event.getY();
            return true;
        }
        case MotionEvent.ACTION_UP: {
            upX = event.getX();
            upY = event.getY();

            float deltaX = downX - upX;
            float deltaY = downY - upY;

       // swipe horizontal?
        if(Math.abs(deltaX) > Math.abs(deltaY))
        {
            if(Math.abs(deltaX) > MIN_DISTANCE){
                // left or right
                if(deltaX > 0) { this.onRightSwipe(); return true; }
                if(deltaX < 0) { this.onLeftSwipe(); return true; }
            }
            else {
                    Log.i(logTag, "Horizontal Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
                    return false; // We don't consume the event
            }
        }
        // swipe vertical?
        else 
        {
            if(Math.abs(deltaY) > MIN_DISTANCE){
                // top or down
                if(deltaY < 0) { this.onDownSwipe(); return true; }
                if(deltaY > 0) { this.onUpSwipe(); return true; }
            }
            else {
                    Log.i(logTag, "Vertical Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
                    return false; // We don't consume the event
            }
        }

            return true;
        }
    }
    return false;
}

}

මට හොඳට වැඩ කරයි!


1
මෙය ඇත්ත වශයෙන්ම මට අභිනය ක්‍රියාකාරිත්වය යෙදීම වඩාත් පහසු කර ඇති අතර "අඩු" රැහැන් අවශ්‍ය විය: D ස්තූතියි h තෝමස්
nemesisfixx

5
මෙය පිළිවෙලට උපයෝගීතා පන්තියක් සේ පෙනේ - නමුත් මම හිතන්නේ ඔබේ සතර ... ස්වයිප් () ක්‍රම අතුරුමුහුණත් විය යුතුයි
කවුරුහරි කොහේ හරි

2
මෙම ප්‍රතිලාභ එහි නොතිබිය යුතුය ("අපි සිද්ධිය පරිභෝජනය නොකරමු" යන පේළිය), එසේ නොවේ ද? එය සිරස් අනුචලන අංගය අක්‍රීය කරයි.
මාරෙක් සෙබෙරා

5
විශේෂයෙන්, onTouch () ක්‍රමය. පළමුව, ඩෙල්ටා එක්ස් ප්‍රමාණවත් තරම් විශාල නොවේ නම්, එය ඩෙල්ටා වයි පරික්ෂා නොකර නැවත පැමිණේ. ප්‍රති result ලය වන්නේ වම්-දකුණු ස්වයිප් කිසි විටෙකත් හඳුනා නොගැනීමයි. දෙවනුව, එය ස්වයිප් එකක් සොයා නොගැනීම නිසා එය සත්‍යයක් නොවිය යුතුය. තෙවනුව, ක්‍රියාවෙන් එය සත්‍යයක් නොවිය යුතුය. මෙය onClick වැනි වෙනත් සවන්දෙන්නෙකුට වැඩ කිරීමෙන් වළක්වයි.
ජෙෆ්රි බ්ලැට්මන්

1
Iot පියොටර් එය යොමු කිරීමක් ඇති වස්තුවක් ක්‍රියාකාරීත්වයේ විෂය පථයට සමාන වන තාක් කල් එය ගැටළුවක් නොවේ. ගැටළුව සිදුවන්නේ ඔබ ක්‍රියාකාරකමට වඩා විශාල විෂය පථයක් ඇති ස්ථානයක යම් ක්‍රියාකාරකමක් ගැන සඳහනක් තබා ඇති විටය ... උදාහරණයක් ලෙස ස්ථිතික සාමාජිකයෙකු වැනි.
ජෙෆ්රි බ්ලැට්මන්

94

මම තෝමස් ෆෑන්ක්හවුසර් වෙතින් විසඳුම තරමක් වෙනස් කර අලුත්වැඩියා කළෙමි

මුළු පද්ධති ගොනු දෙකක්, සිට සමන්විත SwipeInterface හා ActivitySwipeDetector


SwipeInterface.java

import android.view.View;

public interface SwipeInterface {

    public void bottom2top(View v);

    public void left2right(View v);

    public void right2left(View v);

    public void top2bottom(View v);

}

අනාවරකය

import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class ActivitySwipeDetector implements View.OnTouchListener {

    static final String logTag = "ActivitySwipeDetector";
    private SwipeInterface activity;
    static final int MIN_DISTANCE = 100;
    private float downX, downY, upX, upY;

    public ActivitySwipeDetector(SwipeInterface activity){
        this.activity = activity;
    }

    public void onRightToLeftSwipe(View v){
        Log.i(logTag, "RightToLeftSwipe!");
        activity.right2left(v);
    }

    public void onLeftToRightSwipe(View v){
        Log.i(logTag, "LeftToRightSwipe!");
        activity.left2right(v);
    }

    public void onTopToBottomSwipe(View v){
        Log.i(logTag, "onTopToBottomSwipe!");
        activity.top2bottom(v);
    }

    public void onBottomToTopSwipe(View v){
        Log.i(logTag, "onBottomToTopSwipe!");
        activity.bottom2top(v);
    }

    public boolean onTouch(View v, MotionEvent event) {
        switch(event.getAction()){
        case MotionEvent.ACTION_DOWN: {
            downX = event.getX();
            downY = event.getY();
            return true;
        }
        case MotionEvent.ACTION_UP: {
            upX = event.getX();
            upY = event.getY();

            float deltaX = downX - upX;
            float deltaY = downY - upY;

            // swipe horizontal?
            if(Math.abs(deltaX) > MIN_DISTANCE){
                // left or right
                if(deltaX < 0) { this.onLeftToRightSwipe(v); return true; }
                if(deltaX > 0) { this.onRightToLeftSwipe(v); return true; }
            }
            else {
                Log.i(logTag, "Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
            }

            // swipe vertical?
            if(Math.abs(deltaY) > MIN_DISTANCE){
                // top or down
                if(deltaY < 0) { this.onTopToBottomSwipe(v); return true; }
                if(deltaY > 0) { this.onBottomToTopSwipe(v); return true; }
            }
            else {
                Log.i(logTag, "Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
                v.performClick();
            }
        }
        }
        return false;
    }

}

එය මේ ආකාරයට භාවිතා වේ:

ActivitySwipeDetector swipe = new ActivitySwipeDetector(this);
LinearLayout swipe_layout = (LinearLayout) findViewById(R.id.swipe_layout);
swipe_layout.setOnTouchListener(swipe);

ක්‍රියාත්මක කිරීමේදී Activityඔබට ස්වයිප් ඉන්ටර්ෆේස් වෙතින් ක්‍රම ක්‍රියාත්මක කළ යුතු අතර, ස්වයිප් සිදුවීම නරඹන ලද්දේ කුමන ආකාරයෙන්දැයි ඔබට දැනගත හැකිය .

@Override
public void left2right(View v) {
    switch(v.getId()){
        case R.id.swipe_layout:
            // do your stuff here
        break;
    }       
}

මම එය යළිත් වරක් වෙනස් කළෙමි, බලන්න v.performClick();, එය OnClickListener වෙත පරිභෝජනය නොකිරීමට භාවිතා කරයි, එකම දෘෂ්ටියකින් සකසා ඇත්නම්
මාරෙක් සෙබෙරා

හායි, මම සම්පුර්ණ ආරම්භකයෙක් බැවින් මෙම ප්‍රශ්නය සැබවින්ම පැහැදිලි හෝ සුළු කාරණයක් විය හැකි නමුත් කරුණාකර පිළිතුරු දෙන්න. ඔබ ලියා ඇති කොටස එය ලෙස භාවිතා කරයි: ActivitySwipeDetector swipe = නව ActivitySwipeDetector (මෙය); මෙම ප්‍රකාශය ප්‍රධාන ක්‍රියාකාරිත්වයේ කොටසක් වනු ඇත, හරිද? එවිට, "මෙය" ප්‍රධාන ක්‍රියාකාරිත්වයේ ක්‍රියාකාරකමක් වනු ඇත. ඉදිකිරීම්කරු ස්වයිප් ඉන්ටර්ෆේස් හි උදාහරණයක් ගනී. කරුණාකර මට මෙතැනින් උදව් කරන්න. ගොඩක් ස්තුතියි.
චොකලාවා

H චොකෝලාවා නව ප්‍රශ්නයක් නිර්මාණය කරයි, අදහස් දැක්වීම මේ ආකාරයෙන් ඇසීමට සුදුසු ස්ථානයක් නොවේ.
මාරෙක් සෙබෙරා

@MarekSebera මෙය ScrollView & ListView සමඟ ක්‍රියා නොකරයිද? ඒවා හැසිරවිය හැක්කේ කෙසේද?
ඩක් ට්‍රාන්

ile සයිලන්ට්බෑන්ග් නැවතත්, එවැනි ප්‍රශ්න ඇසීමට මෙය ස්ථානයක් නොවේ. කරුණාකර නව ප්‍රශ්න පොතක් සාදන්න.
මාරෙක් සෙබෙරා

65

ඉහත ස්වයිප් අභිනය අනාවරක කේතය ඉතා ප්‍රයෝජනවත් වේ! කෙසේ වෙතත් (REL_SWIPE)නිරපේක්ෂ අගයන්ට වඩා පහත දැක්වෙන සාපේක්ෂ අගයන් භාවිතා කිරීමෙන් මෙම විසඳුම dens නත්ව අ nost ෙයවාදියා කිරීමට ඔබට අවශ්‍ය විය හැකිය(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);

8
මෙය ගෙන ඒම සඳහා +1. API 4 හි ඩෙන්සිටිමෙට්‍රික්ස්.ඩෙන්සිටිපී හඳුන්වා දී ඇති බව සලකන්න. මෙය පසුව ගණනය කිරීම SWIPE_MIN_DISTANCE * dm.density ලෙස වෙනස් කරයි.
තානේ ගීය

ඔබට 160.0f අංකය ලැබුනේ කොහෙන්ද?
ඉගෝර්ගනාපොල්ස්කි

developer.android.com/guide/practices/screens_support.html ඝනත්වය-ස්වාධීන පික්සල (ප්රප) තිරය පික්සල කිරීමට ඩී.පී. ඒකක බවට පරිවර්තනය ඉතා සරළ ය: px = DP * (dpi / 160)
paiego

මම මේ ගැන හැම දෙයක්ම බලාගෙන හිටියා. අන්තර්ජාලයේ onFling () පිළිබඳ කිසිදු උදාහරණයක් මෙය නොමැති අතර එය දුර්වල UX වලට හේතු වේ. ස්තූතියි!
සැන්ඩි

160.0f යනු ඩීපී (ity නත්ව ස්වාධීන පික්සෙල්) පදනම් කරගත් සම්මත ity නත්වය වන 160 ඩීපීඅයි ය. පොදු ස්ථිතික අවසාන int DENSITY_MEDIUM API මට්ටමේ 4 ට එකතු කරන ලදී මධ්‍යම dens නත්ව තිර සඳහා සම්මත ප්‍රමාණාත්මක DPI. නියත අගය: 160 (0x000000a0)
paiego

35

තෝමස් ෆෑන්ක්හවුසර් සහ මාරෙක් සෙබෙරා විසින් යෝජනා කරන ලද මගේ විසඳුමේ අනුවාදය (සිරස් ස්වයිප් හසුරුවන්නේ නැත):

SwipeInterface.java

import android.view.View;

public interface SwipeInterface {

    public void onLeftToRight(View v);

    public void onRightToLeft(View v);
}

ActivitySwipeDetector.java

import android.content.Context;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

public class ActivitySwipeDetector implements View.OnTouchListener {

    static final String logTag = "ActivitySwipeDetector";
    private SwipeInterface activity;
    private float downX, downY;
    private long timeDown;
    private final float MIN_DISTANCE;
    private final int VELOCITY;
    private final float MAX_OFF_PATH;

    public ActivitySwipeDetector(Context context, SwipeInterface activity){
        this.activity = activity;
        final ViewConfiguration vc = ViewConfiguration.get(context);
        DisplayMetrics dm = context.getResources().getDisplayMetrics();
        MIN_DISTANCE = vc.getScaledPagingTouchSlop() * dm.density;
        VELOCITY = vc.getScaledMinimumFlingVelocity();
        MAX_OFF_PATH = MIN_DISTANCE * 2;            
    }

    public void onRightToLeftSwipe(View v){
        Log.i(logTag, "RightToLeftSwipe!");
        activity.onRightToLeft(v);
    }

    public void onLeftToRightSwipe(View v){
        Log.i(logTag, "LeftToRightSwipe!");
        activity.onLeftToRight(v);
    }

    public boolean onTouch(View v, MotionEvent event) {
        switch(event.getAction()){
        case MotionEvent.ACTION_DOWN: {
            Log.d("onTouch", "ACTION_DOWN");
            timeDown = System.currentTimeMillis();
            downX = event.getX();
            downY = event.getY();
            return true;
        }
        case MotionEvent.ACTION_UP: {
            Log.d("onTouch", "ACTION_UP");
            long timeUp = System.currentTimeMillis();
            float upX = event.getX();
            float upY = event.getY();

            float deltaX = downX - upX;
            float absDeltaX = Math.abs(deltaX); 
            float deltaY = downY - upY;
            float absDeltaY = Math.abs(deltaY);

            long time = timeUp - timeDown;

            if (absDeltaY > MAX_OFF_PATH) {
                Log.i(logTag, String.format("absDeltaY=%.2f, MAX_OFF_PATH=%.2f", absDeltaY, MAX_OFF_PATH));
                return v.performClick();
            }

            final long M_SEC = 1000;
            if (absDeltaX > MIN_DISTANCE && absDeltaX > time * VELOCITY / M_SEC) {
                if(deltaX < 0) { this.onLeftToRightSwipe(v); return true; }
                if(deltaX > 0) { this.onRightToLeftSwipe(v); return true; }
            } else {
                Log.i(logTag, String.format("absDeltaX=%.2f, MIN_DISTANCE=%.2f, absDeltaX > MIN_DISTANCE=%b", absDeltaX, MIN_DISTANCE, (absDeltaX > MIN_DISTANCE)));
                Log.i(logTag, String.format("absDeltaX=%.2f, time=%d, VELOCITY=%d, time*VELOCITY/M_SEC=%d, absDeltaX > time * VELOCITY / M_SEC=%b", absDeltaX, time, VELOCITY, time * VELOCITY / M_SEC, (absDeltaX > time * VELOCITY / M_SEC)));
            }

        }
        }
        return false;
    }

}

කරුණාකර කාටහරි මට පන්තියට කතා කරන්නේ කෙසේදැයි කියන්න පුළුවන්ද? ActivitySwipeDetector swipe = නව ActivitySwipeDetector (මෙය); පැහැදිලිවම එවැනි ඉදිකිරීම්කරුවෙකු නොමැති බැවින් දෝෂයක් ලබා දේ. මම ActivitySwipeDetector swipe = නව ActivitySwipeDetector ලබා දිය යුතුද (මෙය ශුන්‍යයි);
abdfahim

B අබ්දුල්ලා ෆාහිම් ක්‍රියාකාරකම් ස්වයිප් ඩිටෙක්ටර් (මෙය, ඔබේ ක්‍රියාකාරිත්වය.);
ඇන්ටන් කෂ්පෝර්

25

මෙම ප්‍රශ්නය යම් ආකාරයක පැරණි එකක් වන අතර 2011 ජූලි මාසයේදී ගූගල් විසින් අනුකූලතා පැකේජය, සංශෝධනය 3) නිකුත් කරන ලද අතර එයට ViewPagerඇන්ඩ්‍රොයිඩ් 1.6 සමඟ ඉහළට වැඩ කරයි. GestureListenerමෙම ප්‍රශ්නය සඳහා පළ කරන ලද පිළිතුරු ඇන්ඩ්‍රොයිඩ් හි ඉතා අලංකාර ලෙස දැනෙන්නේ නැත. ඔබ ඇන්ඩ්‍රොයිඩ් ගැලරියේ ඡායාරූප අතර මාරුවීමට හෝ නව Play වෙළඳපල යෙදුමේ දර්ශන මාරු කිරීමට භාවිතා කරන කේතය සොයන්නේ නම් එය අනිවාර්යයෙන්ම ViewPagerවේ.

වැඩි විස්තර සඳහා සබැඳි කිහිපයක් මෙන්න:


ViewPager හි ඇති එක් ගැටළුවක් නම්, පියාඹන අභිනය සඳහා ඔබට දුර හා ප්‍රවේග පරාමිතීන් පාලනය කළ නොහැකි වීමයි.
almalkawi

ViewPager ගැලරිය තුළ භාවිතා නොවේ.
ඇන්තනි

18

සියලු අභිනයන් සඳහා ඔබට කෙලින්ම භාවිතා කළ හැකි ගොඩනංවන ලද අතුරු මුහුණතක් ඇත:
මූලික මට්ටමේ පරිශීලකයෙකු සඳහා පැහැදිලි කිරීමක් මෙන්න: රූප විස්තරය මෙහි ඇතුළත් කරන්න ආනයන 2 ක් ඇත, දෙකම එකිනෙකට වෙනස් බව තෝරා ගැනීමේදී ප්‍රවේශම් වන්න රූප විස්තරය මෙහි ඇතුළත් කරන්න රූප විස්තරය මෙහි ඇතුළත් කරන්න


1
ඊළඟ පියවර මොනවාද? එම සවන්දෙන්නාව විශේෂිත දර්ශනයකට සකසන්නේ කෙසේද? මෙම මතය කැබැල්ලක කොටසක් නම් කුමක් කළ යුතුද?
ස්ටැන්

16

ViewConfiguration භාවිතා කිරීම සඳහා වෙබය හරහා (සහ මෙම පිටුව) යම් යෝජනාවක් තිබේ. getScaledTouchSlop () සඳහා උපාංග පරිමාණ අගයක් ලබා ගැනීමට SWIPE_MIN_DISTANCE.

getScaledTouchSlop()ස්වයිප් නොව “ අනුචලන සීමාව” දුර සඳහා අදහස් කෙරේ . අනුචලන එළිපත්ත දුර "පිටුව අතර පැද්දීම" එළිපත්ත දුරට වඩා කුඩා විය යුතුය. උදාහරණයක් ලෙස, මෙම ශ්‍රිතය මගේ සැම්සුන් ජීඑස් 2 හි පික්සල් 12 ක් ලබා දෙන අතර මෙම පිටුවේ උපුටා දක්වා ඇති උදාහරණ පික්සල් 100 ක් පමණ වේ.

API මට්ටම 8 (ඇන්ඩ්‍රොයිඩ් 2.2, ෆ්‍රෝයෝ) සමඟ, ඔබට getScaledPagingTouchSlop()පිටු ස්වයිප් සඳහා අදහස් කර ඇත. මගේ උපාංගයේ, එය 24 (පික්සල්) ලබා දෙයි. එබැවින් ඔබ API මට්ටමේ <8 හි සිටී නම්, මම සිතන්නේ "2 * getScaledTouchSlop()" "සම්මත" ස්වයිප් එළිපත්ත විය යුතුය. නමුත් කුඩා තිර සහිත මගේ යෙදුම භාවිතා කරන්නන් මට කීවේ එය ඉතා ස්වල්පයක් බවයි ... මගේ යෙදුමට අනුව ඔබට සිරස් අතට අනුචලනය කර පිටුව තිරස් අතට වෙනස් කළ හැකිය. යෝජිත අගය සමඟ, ඔවුන් සමහර විට අනුචලනය වෙනුවට පිටුව වෙනස් කරයි.


13

සුළු වැඩි දියුණු කිරීමක් ලෙස ද.

උත්සාහක / අල්ලා ගැනීමේ වාරණයට ප්‍රධාන හේතුව වන්නේ ආරම්භක චලනය සඳහා e1 ශුන්‍ය විය හැකි වීමයි. උත්සාහ කිරීමට / අල්ලා ගැනීමට අමතරව, ශුන්‍ය සහ නැවත පැමිණීම සඳහා පරීක්ෂණයක් ඇතුළත් කරන්න. පහත සඳහන් දේට සමාන වේ

if (e1 == null || e2 == null) return false;
try {
...
} catch (Exception e) {}
return false;

12

මෙහි විශිෂ්ට තොරතුරු රාශියක් ඇත. අවාසනාවකට මෙන්, බොහෝ යෙදුම් සඳහා මෙය අත්‍යවශ්‍ය යැයි යමෙකු සිතුවත්, සම්පූර්ණ කරන ලද විවිධ ප්‍රාන්තවල මෙම වෙබ් අඩවි සැකසුම් කේතය විවිධ වෙබ් අඩවි වල විසිරී ඇත.

සුදුසු කොන්දේසි සපුරා ඇත්දැයි සත්‍යාපනය කරන සවන් දෙන්නෙකු නිර්මාණය කිරීමට මම කාලය ගෙන ඇත්තෙමි . පිටු පෙරළීමේ සවන්දෙන්නෙකු මම එකතු කර ඇති අතර එය පිටු පෙරළීම සඳහා එළිපත්ත සපුරාලන බව සහතික කිරීම සඳහා තවත් චෙක්පත් එක් කරයි. මෙම සවන්දෙන්නන් දෙදෙනාම තිරස් හෝ සිරස් අක්ෂයට පහසුවෙන් පියාසර කිරීම සීමා කිරීමට ඔබට ඉඩ සලසයි. පින්තූර ලිස්සා යාම සඳහා එය භාවිතා කරන ආකාරය ඔබට දැක ගත හැකිය . මෙහි සිටින පුද්ගලයින් බොහෝ පර්යේෂණ සිදු කර ඇති බව මම පිළිගනිමි --- මම එය එකට භාවිතා කළ හැකි පුස්තකාලයකට දමා ඇත.

මෙම අවසාන දින කිහිපය නියෝජනය කරන්නේ ඇන්ඩ්‍රොයිඩ් හි කේතීකරණයේ මගේ පළමු පිහියයි; තවත් බොහෝ දේ බලාපොරොත්තු වේ.


ඇඟිලි 2 ක් හරහා ස්වයිප් අභිනය ක්‍රියාත්මක කිරීමට මට අවශ්‍යය. කරුණාකර මට උදව් කරන්න!
ගෞරව් අරෝරා

12

යමෙකුට වැඩ කිරීමේ ක්‍රියාවලියක් අවශ්‍ය නම් මෙය ඉහළින් ඇති පිළිතුරු දෙකේ ඒකාබද්ධ පිළිතුරකි.

package com.yourapplication;

import android.content.Context;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

public abstract class OnSwipeListener implements View.OnTouchListener {

    private final GestureDetector gestureDetector;

    public OnSwipeListener(Context context){
        gestureDetector = new GestureDetector(context, new OnSwipeGestureListener(context));
        gestureDetector.setIsLongpressEnabled(false);
    }

    @Override
    public boolean onTouch(View view, MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
    }

    private final class OnSwipeGestureListener extends GestureDetector.SimpleOnGestureListener {

        private final int minSwipeDelta;
        private final int minSwipeVelocity;
        private final int maxSwipeVelocity;

        private OnSwipeGestureListener(Context context) {
            ViewConfiguration configuration = ViewConfiguration.get(context);
            // We think a swipe scrolls a full page.
            //minSwipeDelta = configuration.getScaledTouchSlop();
            minSwipeDelta = configuration.getScaledPagingTouchSlop();
            minSwipeVelocity = configuration.getScaledMinimumFlingVelocity();
            maxSwipeVelocity = configuration.getScaledMaximumFlingVelocity();
        }

        @Override
        public boolean onDown(MotionEvent event) {
            // Return true because we want system to report subsequent events to us.
            return true;
        }

        // NOTE: see http://stackoverflow.com/questions/937313/android-basic-gesture-detection
        @Override
        public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX,
                               float velocityY) {

            boolean result = false;
            try {
                float deltaX = event2.getX() - event1.getX();
                float deltaY = event2.getY() - event1.getY();
                float absVelocityX = Math.abs(velocityX);
                float absVelocityY = Math.abs(velocityY);
                float absDeltaX = Math.abs(deltaX);
                float absDeltaY = Math.abs(deltaY);
                if (absDeltaX > absDeltaY) {
                    if (absDeltaX > minSwipeDelta && absVelocityX > minSwipeVelocity
                            && absVelocityX < maxSwipeVelocity) {
                        if (deltaX < 0) {
                            onSwipeLeft();
                        } else {
                            onSwipeRight();
                        }
                    }
                    result = true;
                } else if (absDeltaY > minSwipeDelta && absVelocityY > minSwipeVelocity
                        && absVelocityY < maxSwipeVelocity) {
                    if (deltaY < 0) {
                        onSwipeTop();
                    } else {
                        onSwipeBottom();
                    }
                }
                result = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    }

    public void onSwipeLeft() {}

    public void onSwipeRight() {}

    public void onSwipeTop() {}

    public void onSwipeBottom() {}
}

හොඳ ක්‍රියාත්මක කිරීමකට ස්තූතියි. මීට අමතරව මම පරීක්ෂා කිරීමට යෝජනා කරන්නේ absDeltaY > minSwipeDelta, absVelocityY > minSwipeVelocity, absVelocityY < maxSwipeVelocityපමණක් නම් නඩුවේ minSwipeDelta ! = getScaledTouchSlop , minSwipeVelocity ! = getScaledMinimumFlingVelocity , maxSwipeVelocity ! = getScaledMaximumFlingVelocity , එනම්, මේ ඊනියා "පෙරනිමි" (මම අදහස් getScaledTouchSlop, getScaledMinimumFlingVelocity, getScaledMaximumFlingVelocity) අගයන් ඔබේ අනුව කෙරේ, නැතහොත් වෙනස් කරන්නේ නම් පමණි පරීක්ෂා කිරීමට තමන්ගේම පැතුම.
එලියා 12345

මෙම කරුණ අනුව බව ය මූල කේතය "පෙරනිමි 'වටිනාකම් දැනටමත් GestureDetector විසින් පරීක්ෂා, සහ (ඔවුන් තහවුරු කරන්නේ නම් පමණි OnFling පැන රියාරම්භ පමණක් වූ අවස්ථාවක සිදු මාර්ගය විසින් කරන සඳහන් ACTION_UPනොවන ACTION_MOVEහෝ ACTION_POINTER_UPඑනම් එකම ලෙස, සම්පුර්ණයෙන්ම අවබෝධ කරගත් අභිනයක ප්‍රති result ලයක්). (මම වෙනත් API අනුවාදයන් පරික්ෂා කර නැත, එබැවින් අදහස් අගය කරනු ලැබේ).
එලියා 12345

11

පියාසර කිරීම්, ක්ලික් කිරීම්, දිගු ක්ලික් කිරීම් සහ අභිරුචි සිදුවීම් හැසිරවීමට ඔබට ඩ්‍රොයිඩ්වෙයාර් පුස්තකාලය භාවිතා කළ හැකිය . ක්‍රියාත්මක කිරීම පහත මගේ පෙර පිළිතුර මත ගොඩනගා ඇත, නමුත් droidQuery ඉතා සරල, සරල වාක්‍ය ඛණ්ඩයක් සපයයි:

//global variables    private boolean isSwiping = false;
private SwipeDetector.Direction swipeDirection = null;
private View v;//must be instantiated before next call.

//swipe-handling code
$.with(v).swipe(new Function() {
    @Override
    public void invoke($ droidQuery, Object... params) {
        if (params[0] == SwipeDetector.Direction.START)
            isSwiping = true;
        else if (params[0] == SwipeDetector.Direction.STOP) {
            if (isSwiping) {                    isSwiping = false;
                if (swipeDirection != null) {
                    switch(swipeDirection) {
                        case DOWN :                                //TODO: Down swipe complete, so do something
                            break;
                        case UP :
                            //TODO: Up swipe complete, so do something
                            break;
                        case LEFT :
                            //TODO: Left swipe complete, so do something
                            break;
                        case RIGHT :
                            //TODO: Right swipe complete, so do something
                            break;
                        default :                                break;
                    }
                }                }
        }
        else {
            swipeDirection = (SwipeDetector.Direction) params[0];
        }
    }
});

මුල් පිළිතුර

මෙම පිළිතුර මෙහි ඇති අනෙක් පිළිතුරු වලින් සංරචක එකතුවක් භාවිතා කරයි. එය SwipeDetectorපන්තියට අයත් වන අතර එය සිදුවීම් වලට සවන්දීම සඳහා අභ්‍යන්තර අතුරු මුහුණතක් ඇත. මම ද ලබා RelativeLayoutඅභිබවා යාමට කෙසේද යන්න පෙන්වීමට Viewගේ onTouchඅතුල් පහරක් දෙමින් සිදුවීම් සහ අනෙකුත් අනාවරණය සිදුවීම් (ක්ලික් කිරීම් හෝ දිගු ක්ලික් කිරීම් වැනි) යන දෙකම ඉඩ ක්රමය.

SwipeDetector

package self.philbrown;

import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

/**
 * Detect Swipes on a per-view basis. Based on original code by Thomas Fankhauser on StackOverflow.com,
 * with adaptations by other authors (see link).
 * @author Phil Brown
 * @see <a href="http://stackoverflow.com/questions/937313/android-basic-gesture-detection">android-basic-gesture-detection</a>
 */
public class SwipeDetector implements View.OnTouchListener
{
    /**
     * The minimum distance a finger must travel in order to register a swipe event.
     */
    private int minSwipeDistance;

    /** Maintains a reference to the first detected down touch event. */
    private float downX, downY;

    /** Maintains a reference to the first detected up touch event. */
    private float upX, upY;

    /** provides access to size and dimension contants */
    private ViewConfiguration config;

    /**
     * provides callbacks to a listener class for various swipe gestures.
     */
    private SwipeListener listener;

    public SwipeDetector(SwipeListener listener)
    {
        this.listener = listener;
    }


    /**
     * {@inheritDoc}
     */
    public boolean onTouch(View v, MotionEvent event)
    {
        if (config == null)
        {
                config = ViewConfiguration.get(v.getContext());
                minSwipeDistance = config.getScaledTouchSlop();
        }

        switch(event.getAction())
        {
        case MotionEvent.ACTION_DOWN:
            downX = event.getX();
            downY = event.getY();
            return true;
        case MotionEvent.ACTION_UP:
            upX = event.getX();
            upY = event.getY();

            float deltaX = downX - upX;
            float deltaY = downY - upY;

            // swipe horizontal?
            if(Math.abs(deltaX) > minSwipeDistance)
            {
                // left or right
                if (deltaX < 0)
                {
                        if (listener != null)
                        {
                                listener.onRightSwipe(v);
                                return true;
                        }
                }
                if (deltaX > 0)
                {
                        if (listener != null)
                        {
                                listener.onLeftSwipe(v);
                                return true;
                        }
                }
            }

            // swipe vertical?
            if(Math.abs(deltaY) > minSwipeDistance)
            {
                // top or down
                if (deltaY < 0)
                {
                        if (listener != null)
                        {
                                listener.onDownSwipe(v);
                                return true;
                        }
                }
                if (deltaY > 0)
                {
                        if (listener != null)
                        {
                                listener.onUpSwipe(v);
                                return true;
                        }
                }
            }
        }
        return false;
    }

    /**
     * Provides callbacks to a registered listener for swipe events in {@link SwipeDetector}
     * @author Phil Brown
     */
    public interface SwipeListener
    {
        /** Callback for registering a new swipe motion from the bottom of the view toward its top. */
        public void onUpSwipe(View v);
        /** Callback for registering a new swipe motion from the left of the view toward its right. */
        public void onRightSwipe(View v);
        /** Callback for registering a new swipe motion from the right of the view toward its left. */
        public void onLeftSwipe(View v);
        /** Callback for registering a new swipe motion from the top of the view toward its bottom. */
        public void onDownSwipe(View v);
    }
}

ස්වයිප් ඉන්ටර්සෙප්ටර් දර්ශනය

package self.philbrown;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.RelativeLayout;

import com.npeinc.module_NPECore.model.SwipeDetector;
import com.npeinc.module_NPECore.model.SwipeDetector.SwipeListener;

/**
 * View subclass used for handling all touches (swipes and others)
 * @author Phil Brown
 */
public class SwipeInterceptorView extends RelativeLayout
{
    private SwipeDetector swiper = null;

    public void setSwipeListener(SwipeListener listener)
    {
        if (swiper == null)
            swiper = new SwipeDetector(listener);
    }

    public SwipeInterceptorView(Context context) {
        super(context);
    }

    public SwipeInterceptorView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SwipeInterceptorView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onTouchEvent(MotionEvent e)
    {
        boolean swipe = false, touch = false;
        if (swiper != null)
            swipe = swiper.onTouch(this, e);
        touch = super.onTouchEvent(e);
        return swipe || touch;
    }
}

1
ක්ලික් කළ හැකි අංග අඩංගු දර්ශනයකින් මෙය ක්‍රියාත්මක කිරීමට මම උත්සාහ කළෙමි. ක්ලික් කළ හැකි මූලද්‍රව්‍යයක් හරහා ස්වයිප් එකක් ආරම්භ වන විට (උදා: onItemClick සවන්දෙන්නෙකු ලියාපදිංචි කර ඇති ලැයිස්තු දර්ශනයක්), ඉන්පසු onTouchEvent කිසි විටෙකත් ක්‍රියාත්මක නොවේ. මේ අනුව, පරිශීලකයාට ක්ලික් කළ හැකි මූලද්‍රව්‍යයක් හරහා ස්වයිප් එකක් ආරම්භ කළ නොහැකි අතර එය මට අවාසනාවකි. අපගේ ක්ලික් කළ හැකි මූලද්‍රව්‍යයන් තරමක් දර්ශන අවකාශයක් ගන්නා බැවින් අපට තවමත් ස්වයිප් සහාය අවශ්‍ය බැවින් මෙය වටා වැඩ කරන්නේ කෙසේදැයි සොයා ගැනීමට මම තවමත් උත්සාහ කරමි. සමස්ත දර්ශනය සඳහා. ක්ලික් කළ හැකි මූලද්‍රව්‍යයක් හරහා ස්වයිප් ආරම්භ නොවන්නේ නම්, එය පරිපූර්ණව ක්‍රියා කරයි.
ලො-ටැන්

@ ලො-ටැන්, මෙය සිදුවන්නේ ඔබේ ක්ලික් කළ හැකි අයිතමය ළමා දර්ශනයක් වන අතර එය ඉහළින් ඇති SwipeInterceptorViewනිසා එහි ක්ලික් කිරීම මුලින්ම හසුරුවනු ලැබේ. ක්‍රියාත්මක කිරීමෙන් ඔබේම ක්ලික් කිරීමේ යාන්ත්‍රණයක් ක්‍රියාත්මක කිරීමෙන් ඔබට මෙය නිවැරදි කළ හැකිය onTouchListener, නැතහොත් වැඩ කරන ස්ථානයක් ලෙස ක්ලික් කිරීම් වෙනුවට දිගු ක්ලික් කිරීම් වලට සවන්දිය හැකිය (බලන්න View.setOnLongClickListener).
ෆිල්

මම ඇත්තටම ඒ මොහොතේම උත්සාහ කරමි. හෝ ඇදගෙන යාම ආරම්භ කළහොත් ක්ලික් කිරීමේ අවස්ථාව අවලංගු කළ හැකිය :) බොහෝම ස්තූතියි.
ලො-ටැන්

එක් විසඳුමක් නම් ඔබගේ යෙදුමේ සෑම දර්ශනයකටම ස්වයිප් අනාවරකය ඇමිණීමයි. තවත් දෙයක් නම් ඔබේ SwipeInterceptorView හි onInterceptTouchEvent ක්‍රියාත්මක කිරීමයි.
එඩ්වඩ් ෆෝක්

7

මම එහි ප්රමාද පිළිතුරක් නොදන්නා නමුත්, තවමත් මම පෝස්ට් සිටිමි ListView සඳහා ස්වයිප් හඳුනා භාවිතා කරන්නේ කෙසේද? ඒ ListView අයිතමය දී ස්වයිප් ටච් සවන් .

Refrence: Exterminator13 (මෙම පිටුවේ එක් පිළිතුරක්)

එක් ක්‍රියාකාරකමක් ස්විප් ඩිටෙක්ටර්.ක්ලාස් කරන්න

package com.example.wocketapp;

import android.content.Context;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

public class ActivitySwipeDetector implements View.OnTouchListener 
{
    static final String logTag = "SwipeDetector";
    private SwipeInterface activity;
    private float downX, downY;
    private long timeDown;
    private final float MIN_DISTANCE;
    private final int VELOCITY;
    private final float MAX_OFF_PATH;

    public ActivitySwipeDetector(Context context, SwipeInterface activity)
    {
        this.activity = activity;
        final ViewConfiguration vc = ViewConfiguration.get(context);
        DisplayMetrics dm = context.getResources().getDisplayMetrics();
        MIN_DISTANCE = vc.getScaledPagingTouchSlop() * dm.density;
        VELOCITY = vc.getScaledMinimumFlingVelocity();
        MAX_OFF_PATH = MIN_DISTANCE * 2;
    }

    public void onRightToLeftSwipe(View v) 
    {
        Log.i(logTag, "RightToLeftSwipe!");
        activity.onRightToLeft(v);
    }

    public void onLeftToRightSwipe(View v) 
    {
        Log.i(logTag, "LeftToRightSwipe!");
        activity.onLeftToRight(v);
    }

    public boolean onTouch(View v, MotionEvent event) 
    {
        switch (event.getAction()) 
        {
            case MotionEvent.ACTION_DOWN:
            {
                Log.d("onTouch", "ACTION_DOWN");
                timeDown = System.currentTimeMillis();
                downX = event.getX();
                downY = event.getY();
                v.getParent().requestDisallowInterceptTouchEvent(false);
                return true;
            }

        case MotionEvent.ACTION_MOVE:
            {
                float y_up = event.getY();
                float deltaY = y_up - downY;
                float absDeltaYMove = Math.abs(deltaY);

                if (absDeltaYMove > 60) 
                {
                    v.getParent().requestDisallowInterceptTouchEvent(false);
                } 
                else
                {
                    v.getParent().requestDisallowInterceptTouchEvent(true);
                }
            }

            break;

            case MotionEvent.ACTION_UP: 
            {
                Log.d("onTouch", "ACTION_UP");
                long timeUp = System.currentTimeMillis();
                float upX = event.getX();
                float upY = event.getY();

                float deltaX = downX - upX;
                float absDeltaX = Math.abs(deltaX);
                float deltaY = downY - upY;
                float absDeltaY = Math.abs(deltaY);

                long time = timeUp - timeDown;

                if (absDeltaY > MAX_OFF_PATH) 
                {
                    Log.e(logTag, String.format(
                            "absDeltaY=%.2f, MAX_OFF_PATH=%.2f", absDeltaY,
                            MAX_OFF_PATH));
                    return v.performClick();
                }

                final long M_SEC = 1000;
                if (absDeltaX > MIN_DISTANCE && absDeltaX > time * VELOCITY / M_SEC) 
                {
                     v.getParent().requestDisallowInterceptTouchEvent(true);
                    if (deltaX < 0) 
                    {
                        this.onLeftToRightSwipe(v);
                        return true;
                    }
                    if (deltaX > 0) 
                    {
                        this.onRightToLeftSwipe(v);
                        return true;
                    }
                }
                else 
                {
                    Log.i(logTag,
                            String.format(
                                    "absDeltaX=%.2f, MIN_DISTANCE=%.2f, absDeltaX > MIN_DISTANCE=%b",
                                    absDeltaX, MIN_DISTANCE,
                                    (absDeltaX > MIN_DISTANCE)));
                    Log.i(logTag,
                            String.format(
                                    "absDeltaX=%.2f, time=%d, VELOCITY=%d, time*VELOCITY/M_SEC=%d, absDeltaX > time * VELOCITY / M_SEC=%b",
                                    absDeltaX, time, VELOCITY, time * VELOCITY
                                            / M_SEC, (absDeltaX > time * VELOCITY
                                            / M_SEC)));
                }

                 v.getParent().requestDisallowInterceptTouchEvent(false);

            }
        }
        return false;
    }
    public interface SwipeInterface 
    {

        public void onLeftToRight(View v);

        public void onRightToLeft(View v);
    }

}

ඔබගේ ක්‍රියාකාරකම් පන්තියෙන් මේ ආකාරයට අමතන්න:

yourLayout.setOnTouchListener(new ActivitySwipeDetector(this, your_activity.this));

තවද ඔබට ඕවර්රයිඩ් ක්‍රම දෙකක් ලබා දෙන ස්වයිප් ඉන්ටර්ෆේස් ක්‍රියාත්මක කිරීමට අමතක නොකරන්න :

    @Override
    public void onLeftToRight(View v) 
    {
        Log.e("TAG", "L to R");
    }

    @Override
    public void onRightToLeft(View v) 
    {
        Log.e("TAG", "R to L");
    }

MAX_OFF_PATH = 5 * vc.getScaledPagingTouchSlop()මාපටැඟිල්ල ස්වයිප් සඳහා ස්වභාවිකවම සුළු චාපයකින් ගමන් කිරීම වඩාත් පහසු බව මට පෙනී ගියේය.
qix

4

අභිනය යනු ස්පර්ශ තිරය සහ පරිශීලකයා අතර අන්තර්ක්‍රියා අවුලුවාලීමේ සියුම් චලිතයන් ය. තිරයේ පළමු ස්පර්ශය අතර අන්තිම ඇඟිල්ල මතුපිටින් පිටවන මොහොත දක්වා එය පවතී.

ඇන්ඩ්‍රොයිඩ් අපට GestureDetector නමින් පන්තියක් ලබා දෙන අතර එමඟින් පහළට සහ ඉහළට තට්ටු කිරීම, සිරස් අතට හා තිරස් අතට මාරුවීම ( පියාසර කිරීම ), දිගු හා කෙටි මාධ්‍ය, ද්විත්ව තට්ටු යනාදිය වැනි පොදු අභිනයන් අපට හඳුනාගත හැකිය . සවන්දෙන්නන් ඔවුන්ට අනුයුක්ත කරන්න.

අපගේ ක්‍රියාකාරකම් පන්තිය GestureDetector.OnDoubleTapListener (ද්විත්ව තට්ටු අභිනය අනාවරණය කර ගැනීම සඳහා) සහ GestureDetector.OnGestureListener අතුරුමුහුණත් ක්‍රියාත්මක කරන්න. ක්‍රියාත්මක කර සියලු වියුක්ත ක්‍රම ක්‍රියාත්මක කරන්න. වැඩි විස්තර සඳහා. ඔබට https://developer.android.com/training/gestures/detector.html වෙත පිවිසිය හැකිය . අනුග්‍රහයෙනි

ආදර්ශන පරීක්ෂණය සඳහා. GestureDetectorDemo


4

වෙනම පන්තියක් සෑදීමට හෝ කේත සංකීර්ණ කිරීමට ඔබ අකමැති නම්,
ඔබ අකමැති නම් ඔබට OnTouchListener තුළ අභිනය ඩිටෙක්ටර් විචල්‍යයක් සාදා ඔබේ කේතය වඩාත් පහසු කළ හැකිය

namVyuVar ඔබට ලැයිස්තුකරු සැකසීමට අවශ්‍ය දර්ශනයේ ඕනෑම නමක් විය හැකිය

namVyuVar.setOnTouchListener(new View.OnTouchListener()
{
    @Override
    public boolean onTouch(View view, MotionEvent MsnEvtPsgVal)
    {
        flingActionVar.onTouchEvent(MsnEvtPsgVal);
        return true;
    }

    GestureDetector flingActionVar = new GestureDetector(getApplicationContext(), new GestureDetector.SimpleOnGestureListener()
    {
        private static final int flingActionMinDstVac = 120;
        private static final int flingActionMinSpdVac = 200;

        @Override
        public boolean onFling(MotionEvent fstMsnEvtPsgVal, MotionEvent lstMsnEvtPsgVal, float flingActionXcoSpdPsgVal, float flingActionYcoSpdPsgVal)
        {
            if(fstMsnEvtPsgVal.getX() - lstMsnEvtPsgVal.getX() > flingActionMinDstVac && Math.abs(flingActionXcoSpdPsgVal) > flingActionMinSpdVac)
            {
                // TskTdo :=> On Right to Left fling

                return false;
            }
            else if (lstMsnEvtPsgVal.getX() - fstMsnEvtPsgVal.getX() > flingActionMinDstVac && Math.abs(flingActionXcoSpdPsgVal) > flingActionMinSpdVac)
            {
                // TskTdo :=> On Left to Right fling

                return false;
            }

            if(fstMsnEvtPsgVal.getY() - lstMsnEvtPsgVal.getY() > flingActionMinDstVac && Math.abs(flingActionYcoSpdPsgVal) > flingActionMinSpdVac)
            {
                // TskTdo :=> On Bottom to Top fling

                return false;
            }
            else if (lstMsnEvtPsgVal.getY() - fstMsnEvtPsgVal.getY() > flingActionMinDstVac && Math.abs(flingActionYcoSpdPsgVal) > flingActionMinSpdVac)
            {
                // TskTdo :=> On Top to Bottom fling

                return false;
            }
            return false;
        }
    });
});

3

සියල්ලන්ටම: MotionEvent.ACTION_CANCEL නඩුව ගැන අමතක නොකරන්න :

එය ACTION_UP නොමැතිව 30% ස්වයිප් වලින් අමතයි

එය මෙම අවස්ථාවේ දී ACTION_UP ට සමාන වේ


2

මම වඩාත් සාමාන්‍ය පංතියක් තෝරාගෙන, ටොමාස්ගේ පංතිය ගෙන ඔබේ ක්‍රියාකාරකමට හෝ කැබැල්ලට සිදුවීම් යවන අතුරු මුහුණතක් එක් කළෙමි. එය සවන්දෙන්නන් ඉදිකිරීම්කරු මත ලියාපදිංචි කරනු ඇත, එබැවින් ඔබ අතුරු මුහුණත ක්‍රියාත්මක කරන බවට වග බලා ගන්න හෝ ClassCastException කටු වනු ඇත. අතුරුමුහුණත පන්තියේ අර්ථ දක්වා ඇති අවසාන අන්ත හතරෙන් එකක් ලබා දෙන අතර එය ක්‍රියාත්මක කළ දර්ශනය නැවත ලබා දෙනු ඇත.

import android.app.Activity;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class SwipeDetector implements View.OnTouchListener{

    static final int MIN_DISTANCE = 100;
    private float downX, downY, upX, upY;
    public final static int RIGHT_TO_LEFT=1;
    public final static int LEFT_TO_RIGHT=2;
    public final static int TOP_TO_BOTTOM=3;
    public final static int BOTTOM_TO_TOP=4;
    private View v;

    private onSwipeEvent swipeEventListener;


    public SwipeDetector(Activity activity,View v){
        try{
            swipeEventListener=(onSwipeEvent)activity;
        }
        catch(ClassCastException e)
        {
            Log.e("ClassCastException",activity.toString()+" must implement SwipeDetector.onSwipeEvent");
        } 
        this.v=v;
    }
    public SwipeDetector(Fragment fragment,View v){
        try{
            swipeEventListener=(onSwipeEvent)fragment;
        }
        catch(ClassCastException e)
        {
            Log.e("ClassCastException",fragment.toString()+" must implement SwipeDetector.onSwipeEvent");
        } 
        this.v=v;
    }


    public void onRightToLeftSwipe(){   
        swipeEventListener.SwipeEventDetected(v,RIGHT_TO_LEFT);
    }

    public void onLeftToRightSwipe(){   
        swipeEventListener.SwipeEventDetected(v,LEFT_TO_RIGHT);
    }

    public void onTopToBottomSwipe(){   
        swipeEventListener.SwipeEventDetected(v,TOP_TO_BOTTOM);
    }

    public void onBottomToTopSwipe(){
        swipeEventListener.SwipeEventDetected(v,BOTTOM_TO_TOP);
    }

    public boolean onTouch(View v, MotionEvent event) {
        switch(event.getAction()){
        case MotionEvent.ACTION_DOWN: {
            downX = event.getX();
            downY = event.getY();
            return true;
        }
        case MotionEvent.ACTION_UP: {
            upX = event.getX();
            upY = event.getY();

            float deltaX = downX - upX;
            float deltaY = downY - upY;

            //HORIZONTAL SCROLL
            if(Math.abs(deltaX) > Math.abs(deltaY))
            {
                if(Math.abs(deltaX) > MIN_DISTANCE){
                    // left or right
                    if(deltaX < 0) 
                    {
                        this.onLeftToRightSwipe();
                        return true;
                    }
                    if(deltaX > 0) {
                        this.onRightToLeftSwipe();
                        return true; 
                    }
                }
                else {
                    //not long enough swipe...
                    return false; 
                }
            }
            //VERTICAL SCROLL
            else 
            {
                if(Math.abs(deltaY) > MIN_DISTANCE){
                    // top or down
                    if(deltaY < 0) 
                    { this.onTopToBottomSwipe();
                    return true; 
                    }
                    if(deltaY > 0)
                    { this.onBottomToTopSwipe(); 
                    return true;
                    }
                }
                else {
                    //not long enough swipe...
                    return false;
                }
            }

            return true;
        }
        }
        return false;
    }
    public interface onSwipeEvent
    {
        public void SwipeEventDetected(View v , int SwipeType);
    }

}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.