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

时间:2011-06-27 23:40:27

标签: android views scaling

(这有点是Android: How do you scale multiple views together?

的后续行动

我的任务是移植Android上的iPhone / iPad应用程序,该应用程序包含一个简单的图像视图,动画在绝对位置的顶部分层。虽然这在iOS上听起来相当简单,你只需要针对一些可能的屏幕尺寸,但它会让Android变得相当混乱。

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

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

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

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

  3. 由于动画本身必须是交互式的,因此它不是将所有动画放置和放置在与主(背景)图像具有相同大小的透明层上的解决方案,因为它们彼此重叠并且仅相互重叠最上层将是互动的。

    我想到了不同的解决方案:

    1. 要获取主图像的比例因子,我可以检索其measuredWidthmeasuredHeight并将其设置为原始width和{{1}的关系视图。然后我将这个比例因子用于自定义定位并最终自定义缩放。但是,显然height属性仅在onMeasure()调用期间设置,并且在组件树构建之后调用,因此我不知道此解决方案是否可行。

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

    3. 在我的情况下你会做什么?还有什么我还没有考虑过吗?

      提前致谢。

2 个答案:

答案 0 :(得分:1)

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

  1. 我使用ImageView
  2. 将背景图片放在ImageView.setScaleType(ScaleType.FIT_START)的顶部
  3. 我计算了背景图片的比例因子,如下所示:
  4.     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类中使用了此比例,该类加载叠加层以正确定位和缩放视图:
    2.     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));
              }
          }
      

答案 1 :(得分:0)

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