Home | History | Annotate | Download | only in impl
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License
     15  */
     16 
     17 package com.android.incallui.answer.impl;
     18 
     19 import android.content.Context;
     20 import android.content.res.TypedArray;
     21 import android.util.AttributeSet;
     22 import android.view.SurfaceView;
     23 import android.view.View;
     24 import com.android.dialer.common.Assert;
     25 
     26 /**
     27  * A SurfaceView that maintains its aspect ratio to be a desired target value.
     28  *
     29  * <p>The FixedAspectSurfaceView will not be able to maintain the requested aspect ratio if both the
     30  * width and the height are exactly determined by the layout. To avoid this, ensure that either the
     31  * height or the width is adjustable by the view; for example, by setting the layout parameters to
     32  * be WRAP_CONTENT for the dimension that is best adjusted to maintain the aspect ratio.
     33  */
     34 public class FixedAspectSurfaceView extends SurfaceView {
     35 
     36   /** Desired width/height ratio */
     37   private float mAspectRatio;
     38 
     39   private final boolean scaleWidth;
     40   private final boolean scaleHeight;
     41 
     42   public FixedAspectSurfaceView(Context context, AttributeSet attrs) {
     43     super(context, attrs);
     44 
     45     // Get initial aspect ratio from custom attributes
     46     TypedArray a =
     47         context.getTheme().obtainStyledAttributes(attrs, R.styleable.FixedAspectSurfaceView, 0, 0);
     48     scaleHeight = a.getBoolean(R.styleable.FixedAspectSurfaceView_scaleHeight, false);
     49     scaleWidth = a.getBoolean(R.styleable.FixedAspectSurfaceView_scaleWidth, false);
     50     Assert.checkArgument(scaleHeight != scaleWidth, "Must either scale width or height");
     51     setAspectRatio(a.getFloat(R.styleable.FixedAspectSurfaceView_aspectRatio, 1.f));
     52     a.recycle();
     53   }
     54 
     55   /**
     56    * Set the desired aspect ratio for this view.
     57    *
     58    * @param aspect the desired width/height ratio in the current UI orientation. Must be a positive
     59    *     value.
     60    */
     61   public void setAspectRatio(float aspect) {
     62     Assert.checkArgument(aspect >= 0, "Aspect ratio must be positive");
     63     mAspectRatio = aspect;
     64     requestLayout();
     65   }
     66 
     67   @Override
     68   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     69     int width = MeasureSpec.getSize(widthMeasureSpec);
     70     int height = MeasureSpec.getSize(heightMeasureSpec);
     71 
     72     // Do the scaling
     73     if (scaleWidth) {
     74       width = (int) (height * mAspectRatio);
     75     } else if (scaleHeight) {
     76       height = (int) (width / mAspectRatio);
     77     }
     78 
     79     // Override width/height if needed for EXACTLY and AT_MOST specs
     80     width = View.resolveSizeAndState(width, widthMeasureSpec, 0);
     81     height = View.resolveSizeAndState(height, heightMeasureSpec, 0);
     82 
     83     // Finally set the calculated dimensions
     84     setMeasuredDimension(width, height);
     85   }
     86 }
     87