Получите ширину родительского макета

Android Studio 2.0 beta 6

Я пытаюсь использовать ViewPropertyAnimator для перемещения ImageView (ivSettings) внутри панели инструментов, так что это 20dp справа и 20dp сверху, откуда текущее местоположение. И переместить ImageView (ivSearch) 20dp слева и сверху.

ImageViews содержатся в Toolbar,

Это начальное состояние, и я хочу переместить значки в верхние углы на панели инструментов.

Я использую код, чтобы получить ширину, а затем вычесть значение, чтобы получить значение ivSettings, равное 20 dp справа.

final DisplayMetrics displayMetrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
final float widthPx = displayMetrics.widthPixels;

ivSearch.animate()
    .setInterpolator(new AccelerateInterpolator())
    .x(20)
    .y(20)
    .setDuration(250)
    .start();

ivSettings.animate()
    .setInterpolator(new AccelerateInterpolator())
    .x(widthPx - 160)
    .y(20)
    .setDuration(250)
    .start();

Однако, попробовав это на другом размере экрана, я не могу получить точный расчет ширины. Есть ли лучший способ сделать это?

Большое спасибо за любые предложения

2 ответа

Решение

Вы должны быть в состоянии использовать translationX а также translationY свойства для достижения желаемого эффекта. Эти свойства действуют как смещения от исходных координат X и Y вида.

По сути, translationX сместит a View вправо для положительного значения и влево для отрицательного значения из его координаты X. Точно так же translationY смещает View в нижнюю часть для положительных значений и top для отрицательных значений из своей координаты Y.

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

Для значка поиска я предлагаю вам начать с размещения его в верхнем левом углу панели инструментов. Затем установите для translationX и translationY значение 20p. Это должно разместить значок поиска в том же месте, что и ваше изображение. Чтобы переместить значок поиска в верхнем левом углу, все, что вам нужно сделать, это анимировать перевод X & Y от 20 дп до 0 дп.

Повторите то же самое для значка настроек, но установите translationX на -20dp и translationY на 20dp. Таким образом, он будет размещен в той же позиции, что и ваше изображение. Анимируйте оба значения до 0, чтобы добиться желаемой анимации.

Вот код анимации для справки.

ivSearch.animate()
    .setInterpolator(new AccelerateInterpolator())
    .translationX(0) // Takes value in pixels. From 20dp to 0dp
    .translationY(0) // Takes value in pixels. From 20dp to 0dp
    .setDuration(250)
    .start();

ivSettings.animate()
    .setInterpolator(new AccelerateInterpolator())
    .translationX(0) // Takes value in pixels. From -20dp to 0dp
    .translationY(0) // Takes value in pixels. From 20dp to 0dp
    .setDuration(250)
    .start();

// To get pixels from dp
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());

Самое замечательное в этом подходе заключается в том, что вам больше не нужно знать размеры родителя. Все, что вас волнует, это смещения, которые вы указали с помощью translationX а также translationY,

Я считаю, что проблема в том, что методы Animator ожидают, что значения будут в необработанных пиксельных значениях. Похоже, код будет работать только так, как вы собираетесь на экране средней плотности. Например, для экрана hdpi потребуется 30 пикселей, а не 20 пикселей в том же месте. На экранах с более высокой плотностью код в том виде, в котором он существует, подталкивает значки ближе к краям...

Это означает, что нам нужно преобразовать ожидаемое значение dp в необработанные значения пикселей и использовать их для анимации. Существует удобный метод для преобразования dp в px, чтобы он был корректным на каждом устройстве. Я предполагаю, что вы хотите, чтобы левая сторона шестерни находилась на 160dp от правой (обратите внимание, я специально говорю, что левая сторона шестерни, потому что значение 160dp также должно включать ширину изображения шестерни, так как свойство x слева от изображения). Так 160dp = ширина изображения шестерни + желаемое расстояние до правого края. Предположим, у вас есть ресурс ic_gear: Drawable drawable = getResources(). GetDrawable(R.drawable.ic_gear); float bitmapWidth = getIntrinsicWidth();

float rawPX20DPValue = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics());

float rawPXLeftOffset = rawPX20DPValue + bitmapWidth;

ivSearch.animate()
    .setInterpolator(new AccelerateInterpolator())
    .x(rawPX20DPValue)
    .y(rawPX20DPValue)
    .setDuration(250)
    .start();


ivSettings.animate()
    .setInterpolator(new AccelerateInterpolator())
    .x(widthPx - rawPXLeftOffset)
    .y(rawPX20DPValue)
    .setDuration(250)
    .start();

Также проверьте смещения (заполнение) шестерни и значок поиска перед перемещением, поскольку это, вероятно, также повлияет на конечный результат.

Другие вопросы по тегам