Lecture 2 - Intent, onClick, Animation

< CS193A Android Programming

Today: anonymous inner classes, starting intents, animation, toast notifications. Today's example code is all in an activity called Example1Activity -- the key bits of code are pasted in below.

The R.xxx space - "res"

Add Image Resource and ImageView

Alternate Resources

The "drawable-hdpi" etc. folders provide alternate resources depending on runtime details -- screen size, locale, etc. For example, the selector "-hdpi" is for high pixel devices, "-es" for Spanish. Plain "drawable" folder is the base default. Your code can just refer to R.drawable.abbysmile or whatever, and the system does the logic to select the right one automatically. More on this later.

Member Vars, Anonymous Inner Classes

// This class reviews member variables vs. local variables, and shows
// Anonymous Inner Classes which may be new material for some.
class Account {
	private int mBalance;
	// 1. Classic member variable (also known an "instance variable")
	// Can use "m" at name start
	// Exists in the Account object -- outlives any one method call.
	
	public Account() {
		mBalance = 0;
	}
	
	public void deposit(int amt) {
		String logMsg = "deposit:" + amt;
		// 2. logMsg is a local (stack) variable --
		// it exists as temporary storage just while deposit() is running.
		// Contrast to the mBalance variable.
		
		mBalance = mBalance + amt;
	}
	
	/*
	 Variable rules:
	 -Use a member variable if you want storage in the object that outlives
	 any one method. Often set up in onCreate(), modified by methods over time
	 (mBalance is a good example of this pattern).
	 -Use a local variable to hold any temporary result or pointer needed *during*
	 a method run, but not needed after it exits. Local variables are simpler and
	 have better performance, so they are a good default strategy.
	 */
	
	
	// A basic example of an Anonymous Inner Class.
	public void innerDemo() {
		final int temp = mBalance / 10;
		
		Runnable runnable =	
			// This is an "anonymous inner class" -- 3 parts
			new Runnable() {  // 1. The superclass
				public void run() {  // 2. method(s) inside the AIC
					// 3. Code inside the method -- typically this is the part you care
					// about. See notes below
					System.out.println("run() is running");
					deposit(temp);  // Can call methods on the outer object
				}
			};
		/*
		 Code inside an AIC method:
		 1. The AIC creates a separate object with its own methods.
		 However, the AIC keeps a pointer to its owning, outer object to refer
		 to its variables and call its methods too (e.g. deposit()).
		 2. "this" here refers to the AIC itself. Use the syntax "Outer.this" to get
		 a pointer to the outer object.
		 3. Cannot refer to local variables where the AIC was created (e.g. temp)
		 unless they are declared "final".
		 
		 Fun Fact: in Java 8, AIC's are being replaced with a much simpler "lambda"
		 syntax -- yay!
		*/
	}
}

Button OnClickListener

Last bit from previous lecture -- OnClickListener is an AIC.

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        // Store a pointer to editText1. Set up button1 to add a !.
        editText1 = (EditText) findViewById(R.id.editText1);
        Button button = (Button) findViewById(R.id.button1);
        button.setOnClickListener(  // Create a OnClickListener AIC
            new OnClickListener() {
			    public void onClick(View v) {
				    editText1.setText(editText1.getText() + "!");
			    }
            }
        );
	...

Intents

Intent Example -- Open Url

        // Button2: start web intent
        editText2 = (EditText) findViewById(R.id.editText2);
        Button button2 = (Button) findViewById(R.id.button2);
        button2.setOnClickListener(
            new OnClickListener() {
			    public void onClick(View v) {
					Intent intent = new Intent(Intent.ACTION_VIEW); // most common
					intent.setData(Uri.parse(editText2.getText().toString()));
					startActivity(intent);  // Note: this is a ExampleActivity method
					
					/*
					// Alternately, starting a dial intent.
					Intent intent = new Intent(Intent.ACTION_DIAL); // vs. _CALL
					intent.setData(Uri.parse("tel:" + editText2.getText().toString()));
					// uri form should be "tel:555-555-5555"
					*/
				}
            }
        );

Complaint Button

    public void doComplain() {
		Animation animation = AnimationUtils.loadAnimation(this, R.anim.swirl);
		
		// This whole middle piece is optional
		animation.setAnimationListener(
			new AnimationListener() {
                public void onAnimationStart(Animation anim)
                {
                };
                public void onAnimationRepeat(Animation anim)
                {
                };
                public void onAnimationEnd(Animation anim)
                {
                	editText3.setText("");
                	Context context = getApplicationContext();
                	CharSequence text = "Your feedback has been filed appropriately!";
                	int duration = Toast.LENGTH_SHORT;

                	Toast toast = Toast.makeText(context, text, duration);
                	toast.show();
                };

		});
		
		
		editText3.startAnimation(animation);
    }

Animation XML

<<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false">
    <!--  this is in res/anim/swirl.xml -->
    
    <!--  make it smaller for 800ms --> 
    <scale
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:fromXScale="1.0"
        android:toXScale="0.5"
        android:fromYScale="1.0"
        android:toYScale="0.1"
        android:pivotX="50%"
        android:pivotY="50%"
        android:fillAfter="false"
        android:duration="800" />

    <!--  Then rotate and fade out (alpha = 0) for 800 ms -->
    <rotate
        android:fromDegrees="0"
        android:toDegrees="720"
        android:pivotX="50%"
        android:pivotY="50%"
        android:startOffset="800"
        android:duration="800" />
       
    <alpha
        android:fromAlpha="1.0"
        android:toAlpha="0.0"
        android:startOffset="800"
        android:duration="800" />

</set>

AnimationListener, Toast Alert

Previous code example: use AnimationListener AIC to listen for end of animation. At that moment, change text, put up standard "toast" alert.


Homework 2

Add to your homework1 app -- you don't need to turn this in, it's just for practice.