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

Android Studio 2.0 beta 6

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

imageViews содержатся в Toolbar.

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

введите описание изображения здесь

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

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();

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

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

Ответ 1

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

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

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

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

Повторите то же самое для значка настроек, но установите translationX на -20dp и переводY на 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.

Ответ 2

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

Это означает, что нам нужно перевести ожидаемое значение 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();

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