Масштабируйте представление и его многоуровневые подпредставления относительно - PullRequest
2 голосов
/ 28 июня 2011

(Это несколько продолжение для Android: как вы масштабируете несколько видов вместе? )

Моя задача - портировать приложение для iPhone / iPad на Android, которое состоит изпростой вид изображения, на котором анимация накладывается сверху в абсолютных позициях.Хотя это звучит довольно просто на iOS, где нужно настроить таргетинг только на несколько возможных размеров экрана, с Android это выглядит довольно грязно.

Моя текущая настройка такова: RelativeLayout, в который я помещаю свое основное (фоновое) изображениеслева = 0, top = 0 и несколько экземпляров ViewFlipper, используемых в качестве «контейнеров анимации», которые расположены относительно верхнего левого угла экземпляра родительского макета.

У этого подхода есть две основные проблемы:

  1. Позиционированные "анимации" неправильно позиционируются, как только фактический размер макета не соответствует размеру основного фонового изображения.

  2. позиционированные «анимации» также имеют неправильный размер, поскольку, поскольку они обычно имеют «достаточно места» вокруг себя, Android не масштабирует их, чтобы вписать в RelativeLayout (и при этом не будет масштабировать их относительно исходного фона.

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

Я думал о различных решениях:

  1. Чтобы получить масштабный коэффициент основного изображения, я мог бы извлечь его measuredWidth и measuredHeight и установить его в соотношении с исходными width и heightзрения.Затем я бы использовал этот коэффициент масштабирования для пользовательского позиционирования и, в конечном итоге, пользовательского масштабирования.Но, очевидно, свойства measuredWidth/-Height устанавливаются только во время вызова onMeasure () , и он вызывается после построения дерева компонентов, поэтому я не знаю, возможно ли это решение вообще.

  2. Реализация собственного менеджера компоновки и масштабирование / расположение видов соответственно.Я посмотрел на реализацию RelativeLayout, но должен признать, что метод onMeasure () меня немного пугает.

Что бы вы сделали вмое дело?Есть что-то, что я еще не учел?

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 08 июля 2011

Ну, отвечая на мой собственный вопрос - вот способ, которым я решил проблему:

  1. Я поместил фоновое изображение в верхней части моего ImageView с помощью ImageView.setScaleType(ScaleType.FIT_START)
  2. Я рассчитал масштабный коэффициент моего фонового изображения следующим образом:
    WindowManager mgr = (WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE);
    DisplayMetrics metrics = new DisplayMetrics();
    mgr.getDefaultDisplay().getMetrics(metrics);
    Drawable image = context.getResources().getDrawable(R.drawables.someImage);
    float scale = metrics.widthPixels / (float) image.getIntrinsicWidth();
  1. Наконец, я использовал этот масштаб в пользовательском классе ImageView, который загружает оверлеи для правильного позиционирования и масштабирования вида.:
    public class OverlayImage extends ImageView
    {
        private int imgWidth, imgHeight;
        private final float scale;

        public OverlayImage(Context context, int xPos, int yPos, float scale)
        {
            super(context);
            this.scale = scale;

            LayoutParams animParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
                    LayoutParams.WRAP_CONTENT);
            animParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
            animParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
            animParams.leftMargin = (int) (scale * xPos);
            animParams.topMargin = (int) (scale * yPos);
            setLayoutParams(animParams);

            Drawable dr = context.getResources().getDrawable(R.id.someImage);
            setBackgroundDrawable(dr);
            imgWidth = dr.getIntrinsicWidth();
            imgHeight = dr.getIntrinsicHeight();
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
        {
            setMeasuredDimension((int) (scale * imgWidth),
                    (int) (scale * imgHeight));
        }
    }
0 голосов
/ 18 апреля 2013

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

Я решил это немного по-другому, абсолютный макет,и просмотрите все виды и установите координаты и размер каждого.

//This gets the scale of the screen change:
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
Drawable image = getResources().getDrawable(R.drawable.background_image);
float scaleW = displaymetrics.widthPixels / (float)image.getIntrinsicWidth();
float scaleH = displaymetrics.heightPixels / (float)image.getIntrinsicHeight();

//And this scales each view accordingly:
for(int i = 0; i < mainLayout.getChildCount(); i++)
{
    View v = mainLayout.getChildAt(i);
    v.setLayoutParams(new AbsoluteLayout.LayoutParams(
            Math.round(scaleW * v.getMeasuredWidth()),
            Math.round(scaleH * v.getMeasuredHeight()),
            Math.round(scaleW * ((AbsoluteLayout.LayoutParams)v.getLayoutParams()).x),
            Math.round(scaleH * ((AbsoluteLayout.LayoutParams)v.getLayoutParams()).y)));
}
...