相对缩放视图及其分层子视图

发布于 2024-11-17 22:29:32 字数 1386 浏览 5 评论 0原文

(这在某种程度上是 Android:如何一起缩放多个视图? 的后续内容)

我的任务是移植 iPhone / Android 上的 iPad 应用程序由一个简单的图像视图组成,其中动画以绝对位置分层在顶部。虽然这在 iOS 上听起来相当简单,您只需针对几种可能的屏幕尺寸,但在 Android 上却变得相当混乱。

我当前的设置是这样的:RelativeLayout,其中我将主(背景)图像放置在 left = 0、top = 0 上,并将多个 ViewFlipper 实例用作“动画容器”,这些实例相对于父布局实例的左上角定位。

这种方法有两个基本问题:

  1. 一旦布局的实际尺寸与主背景图像的尺寸不匹配,定位的“动画”就会定位错误。

  2. 定位的“动画”的大小也错误,因为它们周围通常有“足够的空间”,Android不会缩放它们以适应RelativeLayout(也不会相对于原始背景缩放它们。< /p>

。动画本身必须是交互式的,但它不是一种将所有动画放置和定位在与主(背景)图像大小相同的透明层上的解决方案,因为它们会相互重叠,并且只有最上面的动画才是交互式的

。解决方案:

  1. 要获取主图像的比例因子,我可以检索其measuredWidthmeasuredHeight并将其设置为原始width<的关系/code> 和 高度 看法。然后我会使用这个比例因子进行自定义定位并最终进行自定义缩放。但是,显然 measuredWidth/-Height 属性仅在 onMeasure() 调用,这是在组件树构建之后调用的,所以我不知道这个解决方案是否可行。

  2. 实现我自己的布局管理器并相应地缩放/定位视图。我查看了 RelativeLayout 的实现,但不得不承认 onMeasure() 方法让我有点害怕。

如果是我的话你会怎么做?还有什么我还没有考虑到的吗?

提前致谢。

(This is somewhat a follow-up on Android: How do you scale multiple views together?)

My task is to port an iPhone / iPad app on Android that consists of a simple image view on which animations are layered on top in absolute positions. While this sounds rather easy on iOS where you only have to target a few possible screen sizes, it gets rather messy with Android.

My current setup is this: A RelativeLayout in which I place my main (background) image on left = 0, top = 0 and multiple ViewFlipper instances used as "animation containers" that are positioned relatively to the upper left corner of the parent layout instance.

This approach has two basic problems:

  1. The positioned "animations" are mis-positioned as soon as the actual size of the layout does not match the size of the main background image.

  2. The positioned "animations" are also mis-sized, because since they usually have "enough space" around themselves, Android doesn't scale them to fit into the RelativeLayout (nor would it scale them relatively to the original background.

Since the animations itself must be interactive, its not a solution to place and position all of the animations on a transparent layer that has the same size as the main (background) image, as they'd overlap each other and only the upper-most would be interactive at all.

I thought of different solutions:

  1. To get the the scale factor of the main image, I could retrieve its measuredWidth and measuredHeight and set this into relation of the original width and height of the view. Then I'd use this scale factor for custom positioning and eventually custom scaling. But, apparently the measuredWidth/-Height properties are only set during the onMeasure() call and this is called after the component tree was built, so I don't know if this solution is feasible at all.

  2. Implement my own layout manager and scale / position the views accordingly. I had a look at the implementation of RelativeLayout, but have to admit that the onMeasure() method scares me a bit.

What would you do in my case? Is there anything I haven't yet taken into account?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

千秋岁 2024-11-24 22:29:32

好吧,回答我自己的问题 - 这是我解决问题的方法:

  1. 我使用 ImageView.setScaleType(ScaleType.FIT_START) 将背景图像放置在我的 ImageView 顶部
  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));
        }
    }

Well, answering my own question - here is the way I resolved the issue:

  1. I placed the background image on the top of my ImageView with ImageView.setScaleType(ScaleType.FIT_START)
  2. I calculated the scale factor of my background image like so:
    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. Finally, I used this scale in a custom ImageView class that loads the overlays to position and scale the view properly:
    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));
        }
    }
妄断弥空 2024-11-24 22:29:32

我最近需要做类似的事情,我还必须将 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)));
}

I lately needed to do something similar, i also had to port a IPad app to android, the screen had many images that had to be in specific locations.

I solved this slightly differently, absolute layout, and run through all the views and set the coordinated and size of each.

//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)));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文