17

Я пишу свой собственный просмотрщик изображений, который позволяет пользователям прокручивать влево/вправо, чтобы увидеть следующее \ предыдущее изображение. Я хочу оживить изменение изображения в соответствии с скоростью движения.Скорость разворота (размах) на разных устройствах Android с одинаковой плотностью

Для обнаружения Fling жест и его скорость, я следовал этому basic gesture detection и сделал, как принятый ответ предложил:

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

    } 

Проблема заключается в том, что я получаю различные значения скорости (velocityX & velocityY) для различных устройств Android с такой же плотность. В основном это означает, что в одном устройстве салфетки чувствуют себя медленными и нечувствительными, а другие устройства чувствуют себя слишком чувствительными.

Я думал, что это может что-то сделать с «по умолчанию» максимальной скоростью на устройстве, которое может быть извлечено с помощью -

ViewConfiguration.get(mContext).getScaledMaximumFlingVelocity() 

Результатов на разных устройствах с одинаковой плотностью не такие же, как Ожидаемый результат:

Samsung S I 480x800 density 1.5 Android 2.1 
    getScaledMinimumFlingVelocity(): 75 
    getScaledMaximumFlingVelocity(): 3600 
    ViewConfiguration.MAXIMUM_FLING_VELOCITY = 4000 

    HTC Desire 480x800 density 1.5 Android 2.3.3 
    getScaledMinimumFlingVelocity(): 75 
    getScaledMaximumFlingVelocity(): 6000 
    ViewConfiguration.MAXIMUM_FLING_VELOCITY = 4000 

    Samsung S III mini 480x800 density 1.5 Android 4.1 
    getScaledMinimumFlingVelocity(): 75 
    getScaledMaximumFlingVelocity(): 12000 
    ViewConfiguration.MAXIMUM_FLING_VELOCITY = 8000 

Вы также можете видеть, что ViewConfiguration имеет 2 различные значения для MAXIMUM_FLING_VELOCITY в Android ниже 4.0 и выше.

Почему разные устройства с одинаковой плотностью и почти одинаковым уровнем api не имеют такой же максимальной скорости? Как я могу получить один и тот же опыт на разных устройствах, когда пользователь делает жестовый салфет? Могу ли я использовать данные максимальной скорости, чтобы сделать единообразный опыт на всех устройствах Android?

ответ

0

Не используйте скорость: она не проста в использовании. Проведите пальцем вправо, это + число, слева - число. Вы могли бы это:

event1.getRawY() 
event2.getRawY() 
event1.getRawX() 
event2.getRawX() 

, чтобы определить, является ли красть было влево или вправо:

если первым событием было больше, чем второй, человек наотмашь слева, но вы можете сказать, если последнее событие было x меньше, чем первое событие, тогда промах пальца человека был достаточно далек и реагировал на него. Вы можете сделать обратное, чтобы салфетка была справа. Кроме того, onFling не распознает небольшие краны и просто касается, поэтому вы можете уйти, не сравнивая скорость или длину расстояния вообще.

+0

Спасибо. Моя проблема заключается не в обнаружении направления или игнорировании жестов без движения, моя проблема связана с различиями в скорости на одних и тех же устройствах плотности после того, как происходит проявление движения. –

+0

@RonTesler Вы можете просто выбирать скорость, основанную на плотности программно. Вы получаете плотность в onCreate и изменяете переменную maxVelocity на основе плотности. – superuser

+0

Извините, я не уверен, что понимаю, как он отвечает на мой вопрос. –

12

У меня была аналогичная проблема. Вместо того чтобы работать непосредственно с максимальной и минимальной скоростью Fling от ViewConfiguration, вы можете нормализовать скорость до значения между 0 и 1.

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 
    float maxFlingVelocity = ViewConfiguration.get(mContext).getScaledMaximumFlingVelocity(); 
    float velocityPercentX = velocityX/maxFlingVelocity;   // the percent is a value in the range of (0, 1] 
    float normalizedVelocityX = velocityPercentX * PIXELS_PER_SECOND; // where PIXELS_PER_SECOND is a device-independent measurement 

Другими словами, velocityPercentX дает «власть» мах как процентов и normalizedVelocityX - это скорость с точки зрения вашей логики приложения (например, ширина изображения в пикселях, не зависящих от устройства).

4

Почему разные устройства с одинаковой плотностью и почти одинаковым уровнем api не имеют такой же максимальной скорости?

Минимальные и максимальные параметры скорости устанавливаются производителем.Различные модели устройств часто используют ту же плотность bucket для целей выбора ресурсов, но обычно не имеют одинаковых физических плотности. Предположим, что существует 4-дюймовый телефон и 5-дюймовый телефон с одинаковыми разрешениями и одинаковая плотность сообщений 1,5. Представьте себе, что прокручивайте обои на обоих экранах с одинаковой скоростью . Показанные пиксели/секунда будут выше на маленьком экране, несмотря на то, что оба телефона имеют одинаковые разрешения и сообщили плотности.

Что делать с минимальной и максимальной скоростью? Допустим, что создатель меньшего экрана определяет 75 пикселей в секунду, а - идеальная минимальная скорость пальца, прежде чем сообщить о бегущем жесте. Любое меньшее будет приводить к случайным выбросам от ошибки прикосновения, любое большее потребует слишком преднамеренного жестов, чтобы что-то бросить. Если производитель большого телефона хотел бы соответствовать тому же совершенному физическому поведению (той же скорости пальца) на меньшем телефоне, им нужно было бы отрегулировать минимальную скорость как меньшее. Изготовителю более крупного устройства потребуется меньше пикселей в секунду, чтобы инициировать выброс из-за физических характеристик. Другие факторы, такие как чувствительность экрана, вероятно, учитываются для разных производителей.

Как я могу получить один и тот же опыт на разных устройствах, когда пользователь делает салфетки?

Используйте скорость, заданную в пикселях в секунду для настройки анимации. Просто избегайте использования независимых по плотности параметров, и вы должны точно соответствовать скорости. Обратите внимание, что это не имеет ничего общего с минимальными или максимальными значениями скорости. Однако вы хотели бы рассчитать свой SWIPE_THRESHOLD_VELOCITY как «сырой» пиксельный показатель, основанный на заявленной плотности. Это как Launcher2 Андроида вычисляет плотность независимой пороговой скорости для элемента домашнего экрана швыряет:

int DENSITY_INDEPENDENT_THRESHOLD = 200; 
Resources r = getResources(); 
float density = r.getDisplayMetrics().density; 
SWIPE_THRESHOLD_VELOCITY = (int)(DENSITY_INDEPENDENT_THRESHOLD * density); 

Обратите внимание, этот порог будет одинаковым для обоих 4" телефон и 5" телефон в приведенном выше примере. Это не влияет на фактические скоростей, потому что мы говорим только о пороге здесь. Вам просто нужно будет прокручивать на 20% быстрее на 5-дюймовом телефоне, чем на 4-дюймовом телефоне, чтобы сломать порог. Пусковая установка Android использует DENSITY_INDEPENDENT_THRESHOLD -1500 в направлении y, но 200 звуков, подходящих для вашего приложения.

Могу ли я использовать данные максимальной скорости, чтобы сделать единообразный опыт между всеми устройствами Android?

No. Макс. Скорость - это краевой кейс, который вам не нужно анимировать правильно. Я сомневаюсь, что пользователи будут бросать что-либо с максимальной скоростью, если они не играют в игру, и пользователям все равно, будет ли анимация идеально соответствовать скорости 6000 пикселей в секунду.

TL; DR Используйте исходные скорости из аргументов onFling, чтобы точно настроить анимацию и скорость совпадения. Избегайте использования независимых по плотности параметров для настройки анимации fling.

Смежные вопросы