# CSE 340 Lab 1: Doodle (Winter 2020) ## Introduction to Doodle .title-slide-logo[ ![:img Android Logo](img/android-logo.png) ] --- .left-column[ ## **Library** (and Inheritance Hierarchy)
graph TD Activity[Activity] Activity -->|...| Doodler[Doodler] Doodler --> Part1[Part1] Part1 --> Part1Activity[Part1Activity] Part1 --> Part2Activity[Part2Activity] class Part1,Part1Activity,Part2Activity yellow class Activity,Doodler green
] .right-column[ ## Android Classes we are using in Doodle and how they relate - Doodler (which you don't edit) *extends* [Activity](https://developer.android.com/reference/android/app/Activity) - Part1 *extends* Doodler. It implements *helper methods* for Part1Activity and Part2Activity. - Part1Activity and Part2Activity both extend Part1 ] --- layout:none .title[Running Sample Code] .body[ When you accept the assignment on GitGrade, a repository containing the starter code is generated for you on CSE GitLab. You **MUST** work within this assignment, as it will be turned in via GitGrade when it is due. Please clone and use the repository and commit and push your work regularly. Not only will doing so protect your code, but it will also allow course staff to look at your code and it will allow you to easily pull any changes we make to the assignment source.You can find instructions on setting up and maintaining a forked repository [here](https://help.github.com/en/articles/working-with-forks). ] --- ## Cloning Doodle .left-column[ You can find your unique repo by the notification email or by going to [GitLab](https://gitlab.cs.washington.edu) or via the [GitGrade](https://gitgrade.cs.washington.edu) interface. ] .right-column[ ![:img Android Studio splash screen, 30%](img/doodle-clone-1.png) ![:img Android Studio clone dialog, 30%](img/doodle-clone-2.png) ] --- .title[Open project in Android Studio] .body[ - Run configurations should be automatically imported from Gradle - If not, `build` should trigger an import - Run with ► - Connect an android device by USB or create a new virtual device - If by USB, debugging must be enabled on the device ] --- .title[Implementing `addImage`] .body[ ```java private ImageView addImage(FrameLayout mainCanvas, String imageName, Float x, Float y, int size); ``` ### Params: - `mainCanvas`: Canvas in which to render the image. - `imageName`: Filename of image to draw in `res/drawable`. ] -- .body[ - `x`: Horizontal distance from top-left corner of canvas to top-left of image. - `y`: Veritcal distance from top-left corner of canvas to top-left of image. - `size`: Width and height of rendered image, in pixels. ] --- .title[Implementing `addImage`] .body[ ### Returns: - An `ImageView` which has been added to the canvas. ] --- .title[Implementing `addImage`] .body[ Break down into component steps, look up documentation, and implement 1. Create `ImageView` ] -- .body[ 2. Add new view to canvas ] -- .body[ 3. Position and set view size ] -- .body[ 4. Set view contents ] --- .title[Implementing `addImage`] .body[ ```java private ImageView addImage(FrameLayout mainCanvas, String imageName, Float x, Float y, int size) { // Create ImageView and add it to mainCanvas. ImageView imageView = new ImageView(this); // Add imageView to mainCanvas // Set imageView size and position // Set imageView contents using filename return imageView; } ``` ] --- .title[Implementing `addImage`] .body[ ```java private ImageView addImage(FrameLayout mainCanvas, String imageName, Float x, Float y, int size) { // Create ImageView and add it to mainCanvas. ImageView imageView = new ImageView(this); mainCanvas.addView(imageView); // Set imageView size and position // Set imageView contents using filename return imageView; } ``` ] --- .title[Implementing `addImage`] .body[ ```java private ImageView addImage(FrameLayout mainCanvas, String imageName, Float x, Float y, int size) { // Create ImageView and add it to mainCanvas. ImageView imageView = new ImageView(this); mainCanvas.addView(imageView); imageView.getLayoutParams().height = size; imageView.getLayoutParams().width = size; // Set imageView contents using filename return imageView; } ``` ] --- .title[Implementing `addImage`] .body[ ```java private ImageView addImage(FrameLayout mainCanvas, String imageName, Float x, Float y, int size) { // Create ImageView and add it to mainCanvas. ImageView imageView = new ImageView(this); mainCanvas.addView(imageView); imageView.getLayoutParams().height = size; imageView.getLayoutParams().width = size; imageView.setX(x); imageView.setY(y); // Set imageView contents using filename return imageView; } ``` ] --- .title[Implementing `addImage`] .body[ ```java private ImageView addImage(FrameLayout mainCanvas, String imageName, Float x, Float y, int size) { // Create ImageView and add it to mainCanvas. ImageView imageView = new ImageView(this); mainCanvas.addView(imageView); imageView.getLayoutParams().height = size; imageView.getLayoutParams().width = size; imageView.setX(x); imageView.setY(y); int resID = getResources().getIdentifier(imageName, "drawable", getPackage()); imageView.setImageResource(resID); return imageView; } ``` ] --- ## `ValueAnimator` - Keeps track of the animation's timing (how long its been running and current value of property) - Contains a `TimeInterpolator` that defines the type of interpolation for the value over time - Contains a `TypeEvaluator` that figures out how to calculate values for the property being animated ```java ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f); animation.setDuration(1000); // Starts the animation animation.start(); // TODO: need to listen for updates to get the returned value ``` --- .title[How do we use pacing functions for this?] .body[ ![:img Picture of a curve transforming motion over time to create a pacing effect, 40%](img/drawing/pacing.png) - Time normalized with respect to animation interval (0...1) - Normalized time is transformed by pacing function (0…1) - Paced value is then fed to curve function to get final value ] --- .title[XML shown in class] .body[ ```xml
``` ] --- ```java package com.example.myapplication; //imports... public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ImageView view = new ImageView(this); setContentView(view); Bitmap bitmap = Bitmap.createBitmap(100,100, Bitmap.Config.ARGB_8888); view.setImageBitmap(bitmap); Canvas c = new Canvas(bitmap); Paint p = new Paint(); c.drawCircle(10,10,5,p); ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f); anim.setDuration(2000); anim.start(); Animator anim2 = (Animator) AnimatorInflater.loadAnimator(this, R.animator.sample); anim2.setTarget(view); anim2.setDuration(2000); anim2.start(); } } ```