1 /*
2  * Copyright (C) 2021 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.test.hwui;
18 
19 import android.animation.ObjectAnimator;
20 import android.app.Activity;
21 import android.content.Context;
22 import android.graphics.Canvas;
23 import android.graphics.Color;
24 import android.graphics.Paint;
25 import android.graphics.RecordingCanvas;
26 import android.graphics.RenderNode;
27 import android.os.Bundle;
28 import android.view.Gravity;
29 import android.view.SurfaceHolder;
30 import android.view.SurfaceHolder.Callback;
31 import android.view.SurfaceView;
32 import android.view.animation.LinearInterpolator;
33 import android.widget.FrameLayout;
34 
35 public class StretchySurfaceViewActivity extends Activity implements Callback {
36     SurfaceView mSurfaceView;
37     ObjectAnimator mAnimator;
38 
39     class MySurfaceView extends SurfaceView {
40         boolean mSlow;
41         boolean mScaled;
42         int mToggle = 0;
43 
MySurfaceView(Context context)44         public MySurfaceView(Context context) {
45             super(context);
46             setOnClickListener(v -> {
47                 mToggle = (mToggle + 1) % 4;
48                 mSlow = (mToggle & 0x2) != 0;
49                 mScaled = (mToggle & 0x1) != 0;
50 
51                 mSurfaceView.setScaleX(mScaled ? 1.6f : 1f);
52                 mSurfaceView.setScaleY(mScaled ? 0.8f : 1f);
53 
54                 setTitle("Slow=" + mSlow + ", scaled=" + mScaled);
55                 invalidate();
56             });
57             setWillNotDraw(false);
58         }
59 
60         @Override
draw(Canvas canvas)61         public void draw(Canvas canvas) {
62             super.draw(canvas);
63             if (mSlow) {
64                 try {
65                     Thread.sleep(16);
66                 } catch (InterruptedException e) {}
67             }
68         }
69 
setMyTranslationY(float ty)70         public void setMyTranslationY(float ty) {
71             setTranslationY(ty);
72             if (mSlow) {
73                 invalidate();
74             }
75         }
76 
getMyTranslationY()77         public float getMyTranslationY() {
78             return getTranslationY();
79         }
80     }
81 
82     @Override
onCreate(Bundle savedInstanceState)83     protected void onCreate(Bundle savedInstanceState) {
84         super.onCreate(savedInstanceState);
85 
86         FrameLayout content = new FrameLayout(this) {
87             {
88                 setWillNotDraw(false);
89             }
90 
91             @Override
92             protected void onDraw(Canvas canvas) {
93                 Paint paint = new Paint();
94                 paint.setAntiAlias(true);
95                 paint.setColor(Color.RED);
96                 paint.setStyle(Paint.Style.STROKE);
97                 paint.setStrokeWidth(10f);
98                 canvas.drawLine(0f, 0f, getWidth(), getHeight(), paint);
99                 super.onDraw(canvas);
100 
101                 RenderNode node = ((RecordingCanvas) canvas).mNode;
102                 node.stretch(0f,
103                         1f, 400f, 400f);
104             }
105         };
106 
107         mSurfaceView = new MySurfaceView(this);
108         mSurfaceView.getHolder().addCallback(this);
109 
110         final float density = getResources().getDisplayMetrics().density;
111         int size = (int) (200 * density);
112 
113         content.addView(mSurfaceView, new FrameLayout.LayoutParams(
114                 size, size, Gravity.CENTER_HORIZONTAL | Gravity.TOP));
115         mAnimator = ObjectAnimator.ofFloat(mSurfaceView, "myTranslationY",
116                 0, size);
117         mAnimator.setRepeatMode(ObjectAnimator.REVERSE);
118         mAnimator.setRepeatCount(ObjectAnimator.INFINITE);
119         mAnimator.setDuration(1000);
120         mAnimator.setInterpolator(new LinearInterpolator());
121         setContentView(content);
122     }
123 
124     @Override
surfaceCreated(SurfaceHolder holder)125     public void surfaceCreated(SurfaceHolder holder) {
126     }
127 
128     @Override
surfaceChanged(SurfaceHolder holder, int format, int width, int height)129     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
130         Canvas canvas = holder.lockCanvas();
131         canvas.drawColor(Color.WHITE);
132 
133         Paint paint = new Paint();
134         paint.setAntiAlias(true);
135         paint.setColor(Color.GREEN);
136         paint.setStyle(Paint.Style.STROKE);
137         paint.setStrokeWidth(10f);
138         canvas.drawLine(0, 0, width, height, paint);
139 
140         holder.unlockCanvasAndPost(canvas);
141     }
142 
143     @Override
surfaceDestroyed(SurfaceHolder holder)144     public void surfaceDestroyed(SurfaceHolder holder) {
145     }
146 
147     @Override
onResume()148     protected void onResume() {
149         super.onResume();
150         mAnimator.start();
151     }
152 
153     @Override
onPause()154     protected void onPause() {
155         mAnimator.pause();
156         super.onPause();
157     }
158 }
159