@Override
protected void onDraw(Canvas canvas) {
}
@Override
protected void onDraw(Canvas canvas) {
// Draw background.
canvas.drawBitmap(mBackground, 0, 0, null);
}
@Override
protected void onDraw(Canvas canvas) {
// Draw background.
canvas.drawBitmap(mBackground, 0, 0, null);
// Make sure we get re-drawn as soon as possible
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
// Draw background.
canvas.drawBitmap(mBackground, 0, 0, null);
// Draw each of the two lines
long elapsedTime = System.currentTimeMillis() - mStartTimestamp;
drawLine(canvas, computeNewAngle(elapsedTime, 1000), LINE_HEIGHT_LONG);
drawLine(canvas, computeNewAngle(elapsedTime, 10000), LINE_HEIGHT_SHORT);
// Make sure we get re-drawn as soon as possible
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
// Draw background.
canvas.drawBitmap(mBackground, 0, 0, null);
// Draw each of the two lines
long elapsedTime = System.currentTimeMillis() - mStartTimestamp;
drawLine(canvas, computeNewAngle(elapsedTime, 1000), LINE_HEIGHT_LONG);
drawLine(canvas, computeNewAngle(elapsedTime, 10000), LINE_HEIGHT_SHORT);
// Make sure we get re-drawn as soon as possible
invalidate();
}
private void drawLine(Canvas canvas, int angle, int lineHeight) {
canvas.save();
canvas.rotate(angle, mCenterX, mCenterY);
canvas.drawRect(mCenterX - LINE_WIDTH / 2,
mCenterY - LINE_OFFSET - lineHeight,
mCenterX + LINE_WIDTH / 2,
mCenterY - LINE_OFFSET,
mLinePaint);
canvas.restore();
}
Spring dynamics for Android"
T:40
F: 2
T:40
F:25
T:95
F: 2
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/background"/>
</FrameLayout>
public class MainActivity extends AppCompatActivity {
private ImageView mItemView;
private int mItemWidth;
private int mItemHeight;
private int mWindowWidth;
private int mWindowHeight;
...
}
private void initializeRebound() {
// Setup spring system and the springs
SpringSystem springSystem = SpringSystem.create();
SpringConfig config = new SpringConfig(60, 8);
mSpringX = springSystem.createSpring()
.setSpringConfig(config);
mSpringY = springSystem.createSpring()
.setSpringConfig(config);
}
@Override
protected void onStart() {
// Setup layout and initialize fields
...
initializeRebound();
}
private void initializeRebound() {
// Setup spring system and the springs
SpringSystem springSystem = SpringSystem.create();
SpringConfig config = new SpringConfig(60, 8);
mSpringX = springSystem.createSpring()
.setSpringConfig(config);
mSpringY = springSystem.createSpring()
.setSpringConfig(config);
// Initial setup
mSpringX.setCurrentValue(mWindowWidth / 2);
mSpringY.setCurrentValue(mWindowHeight / 2);
// ... <To be continued>
}
@Override
protected void onStart() {
// Setup layout and initialize fields
...
initializeRebound();
}
private void updateView() {
mItemView.setX((float) mSpringX.getCurrentValue() - mItemWidth / 2);
mItemView.setY((float) mSpringY.getCurrentValue() - mItemHeight / 2);
}
private void initializeRebound() {
// Setup spring system and the springs and perform initial setup
...
// Trigger the initial view update
updateView()
// Listen for value changes received from the spring system
mSpringX.addListener(new SimpleSpringListener() {
@Override
public void onSpringUpdate(Spring spring) {
updateView();
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN
|| event.getAction() == MotionEvent.ACTION_MOVE) {
mSpringX.setEndValue(event.getX());
mSpringY.setEndValue(event.getY());
return true;
}
return super.onTouchEvent(event);
}
private void initializeRebound() {
...
mSpringX.addListener(new SimpleSpringListener() {
@Override
public void onSpringEndStateChange(Spring spring) {
mSpringSize.setEndValue(0.7);
}
});
mSpringSize = springSystem.createSpring().addListener(new SimpleSpringListener() {
public void onSpringUpdate(Spring spring) {
updateViewSize();
}
});
mSpringSize.setCurrentValue(1);
updateViewSize();
}
private void updateViewSize() {
mItemView.setScaleX((float) mSpringSize.getCurrentValue());
mItemView.setScaleY((float) mSpringSize.getCurrentValue());
}
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
mSpringSize.setEndValue(1);
} else ...
}
(since API Level 11)
mSceneRoot = (ViewGroup) findViewById(R.id.root);
mScene1 = Scene.getSceneForLayout(mSceneRoot, R.layout.scene1, this);
mScene2 = Scene.getSceneForLayout(mSceneRoot, R.layout.scene2, this);
mSceneRoot = (ViewGroup) mSceneRootView;
// View hierarchy that will be added as a child of the scene root when entering the scene
mViewHierarchy = (ViewGroup) mSceneView;
mScene = new Scene(mSceneRoot, mViewHierarchy);
Generation from layout resource files
Defining them via code and existing views
<fade xmlns:android="http://schemas.android.com/apk/res/android" />
// Create and define a simple transitions
Transition fadeTransition = new Fade();
// Or combine multiple ones in a set
TransitionSet transitionSet = new TransitionSet()
.addTransition(new Scale(0.3f))
.addTransition(new Fade())
.setInterpolator(new LinearOutSlowInInterpolator());
From a resource file
Via code definition
Transition transition = TransitionInflater.from(mContext)
.inflateTransition(R.transition.fade_transition);
// Update the hierarchy inside the scene root with the one from the ending scene,
// running the animations defined by the transition
TransitionManager.go(endScene, transition);
// Start recording changes to the view hierarchy
TransitionManager.beginDelayedTransition(rootView, transition);
// Add the new View to the hierarchy
rootView.addView(mNewTextView);
Applying the transition with a target scene
Applying the transition without a scene
@Override
public void onClick (View v){
TransitionManager.beginDelayedTransition(mViewContainer);
mIsVisible = !mIsVisible;
mTextView.setVisibility(mIsVisible ? View.VISIBLE : View.GONE);
}
@Override
public void onClick (View v){
TransitionManager.beginDelayedTransition(mViewContainer,
new ChangeText().setChangeBehavior(ChangeText.CHANGE_BEHAVIOR_OUT_IN));
textView.setText(isSecondText ?
"Thanks! Another tap?" :
"Hi, i am a text. Tap on me!");
}
@Override
public void onClick(View v) {
Transition transition = new ChangeBounds()
.setPathMotion(new ArcMotion())
.setDuration(500);
TransitionManager.beginDelayedTransition(viewContainer,
transition);
mToRightAnimation = !mToRightAnimation;
LayoutParams params = (LayoutParams) button.getLayoutParams();
params.gravity = mToRightAnimation ?
(Gravity.RIGHT | Gravity.BOTTOM) :
(Gravity.LEFT | Gravity.TOP);
button.setLayoutParams(params);
}
public void onItemClick(View view) {
final Rect viewRect = new Rect();
view.getGlobalVisibleRect(viewRect);
Transition transition1 = new Explode()
.setEpicenterCallback(new EpicenterCallback() {
@Override
public Rect onGetEpicenter(Transition transition) {
return viewRect;
}
});
TransitionSet set = new TransitionSet()
.addTransition(transition1.excludeTarget(view, true))
.addTransition(new Fade().addTarget(view));
TransitionManager.beginDelayedTransition(mRecyclerView, set);
mRecyclerView.setAdapter(null);
}
<selector xmlns:android="...">
<item android:state_pressed="true">
<set>
<objectAnimator
android:duration="300"
android:propertyName="alpha"
android:valueFrom="1"
android:valueTo="0.4"
android:valueType="floatType"/>
<objectAnimator
android:duration="300"
android:propertyName="scaleX"
android:valueFrom="1"
android:valueTo="1.2"
android:valueType="floatType"/>
</set>
</item>
...
</selector>
<Button ...
android:stateListAnimator="@anim/demo_selector"/>
public class CustomButton extends Button {
...
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
int targetRotation = isPressed() ? 180 : 0;
if (targetRotation != getRotation())
this.animate().rotation(targetRotation);
}
}