I am trying to create an image slide show that is similar to this
I found this tutorial which shows me how to make images fade into each other, which works really well, but I can't find any examples how to make it do the movement/scaling at the same time so I am trying to adapt it.
I have added a scale animation and put that along with the alpha animation in an animationset but I can't get it to work correctly, it is only doing the animation on every other im开发者_运维知识库age and then when the zoom starts it zooms one way and switches and then zooms the other way.
I am reasonably new to Android have not done any animations before and am having difficultly understanding how the example is working. Therefore I am having difficulty amending it.
Can anyone help me work out what I am doing wrong? I'm starting to pull my hair out!
My java code is:
public class TopListActivity extends Activity {
ImageView slide_0;
ImageView slide_1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test2);
slide_0 = (ImageView) findViewById(R.id.slide_1);
slide_1 = (ImageView) findViewById(R.id.slide_2);
}
private static class AnimationTimer extends TimerTask implements
AnimationListener {
TopListActivity topList;
Vector<BitmapDrawable> images;
int count = 0;
public AnimationTimer(TopListActivity _topList) {
this.topList = _topList;
this.images = new Vector<BitmapDrawable>();
Resources resources = topList.getResources();
images.add((BitmapDrawable) resources.getDrawable(R.drawable.one));
images.add((BitmapDrawable) resources.getDrawable(R.drawable.two));
images.add((BitmapDrawable) resources.getDrawable(R.drawable.three));
images.add((BitmapDrawable) resources.getDrawable(R.drawable.four));
images.add((BitmapDrawable) resources.getDrawable(R.drawable.five));
images.add((BitmapDrawable) resources.getDrawable(R.drawable.six));
if (this.images.size() > 0) {
this.topList.slide_0.setBackgroundDrawable(this.images.get(0));
if (this.images.size() > 1) {
this.topList.slide_1.setBackgroundDrawable(this.images
.get(1));
}
}
this.count = 1;
}
public void launch() {
if (this.images.size() >= 2) {
(new Timer(false)).schedule(this, 100);
}
}
@Override
public void run() {
this.doit();
this.cancel();
}
private void doit() {
if ((this.count % 2) == 0) {
AnimationSet set = new AnimationSet(false);
AlphaAnimation animation = new AlphaAnimation(1.0f, 0.0f);
animation.setStartOffset(5000);
animation.setDuration(3000);
animation.setFillAfter(true);
ScaleAnimation zoom = new ScaleAnimation(1, 1.20f, 1, 1.20f);
zoom.setStartOffset(0);
zoom.setDuration(8000);
zoom.setFillAfter(true);
set.addAnimation(animation);
set.addAnimation(zoom);
set.setAnimationListener(this);
this.topList.slide_1.startAnimation(set);
} else {
AnimationSet set = new AnimationSet(false);
AlphaAnimation animation = new AlphaAnimation(0.0f, 1.0f);
animation.setStartOffset(5000);
animation.setDuration(3000);
animation.setFillAfter(true);
ScaleAnimation zoom = new ScaleAnimation(1.20f, 1, 1.20f, 1);
zoom.setStartOffset(0);
zoom.setDuration(8000);
zoom.setFillAfter(true);
set.addAnimation(animation);
set.addAnimation(zoom);
set.setAnimationListener(this);
this.topList.slide_1.startAnimation(set);
}
}
public void onAnimationEnd(Animation animation) {
if ((this.count % 2) == 0) {
this.topList.slide_1.setBackgroundDrawable(this.images
.get((this.count + 1) % (this.images.size())));
} else {
this.topList.slide_0.setBackgroundDrawable(this.images
.get((this.count + 1) % (this.images.size())));
}
this.count++;
this.doit();
}
public void onAnimationRepeat(Animation animation) {
}
public void onAnimationStart(Animation animation) {
}
}
@Override
public void onResume() {
super.onResume();
(new AnimationTimer(this)).launch();
}
}
and my layout is:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/slide_1"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/slide_2"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
Finally sorted it... it's very long winded as I couldn't get to grips with the animation end event because of the multiple animations.. so probably not the best way but it works and I'm happy!
For anyone who wants to know how.. or wants to adapt it to make it better here it is:
Main Activity (MyTransition.java):
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import java.util.Vector;
public class MyTransition extends AppCompatActivity {
ImageView slide_0;
ImageView slide_1;
ImageView lastSlide;
Vector<Integer> imageIds;
LinearLayout linLayout;
int count = 0;
private Handler transparencyHandler = new Handler();
private Handler timerHandler = new Handler();
private Runnable transparencyTimer = new Runnable() {
public void run() {
if (lastSlide == slide_0) {
slide_1.setBackgroundColor(getResources().getColor(android.R.color.transparent));
slide_1.setImageResource(0);
} else {
slide_0.setBackgroundColor(getResources().getColor(android.R.color.transparent));
slide_0.setImageResource(0);
}
}
};
private Runnable timer = new Runnable() {
public void run() {
if (lastSlide == slide_0) {
slide_1.setImageResource(0);
slide_1.setImageResource(imageIds.get((count + 1)
% (imageIds.size())));
slide_1.startAnimation(AnimationUtils
.loadAnimation(MyTransition.this,
R.anim.transition_down));
lastSlide = slide_1;
} else {
slide_0.setImageResource(0);
slide_0.setImageResource(imageIds.get((count + 1)
% (imageIds.size())));
slide_0.startAnimation(AnimationUtils
.loadAnimation(MyTransition.this,
R.anim.transition_up));
lastSlide = slide_0;
}
count++;
transparencyHandler.postDelayed(transparencyTimer, 1000);
timerHandler.postDelayed(timer, 8000);
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test2);
slide_0 = (ImageView) findViewById(R.id.slide_1);
slide_1 = (ImageView) findViewById(R.id.slide_2);
imageIds = new Vector<Integer>();
imageIds.add(R.drawable.first_image);
imageIds.add(R.drawable.second_image);
// Load Image 1
slide_0.setImageResource(imageIds.get(0));
slide_0.startAnimation(AnimationUtils.loadAnimation(this,
R.anim.transition_down));
lastSlide = slide_0;
timerHandler.postDelayed(timer, 8000);
}
}
Layout (test2.xml):
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/slide_1"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerCrop" />
<ImageView
android:id="@+id/slide_2"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerCrop" />
</FrameLayout>
Animation (transition_down.xml):
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<alpha
android:fromAlpha="0.0"
android:toAlpha="2.0"
android:duration="2000"
android:repeatCount="0"
android:fillAfter="true" />
<scale
android:fromXScale="1"
android:toXScale="1.2"
android:fromYScale="1"
android:toYScale="1.2"
android:duration="10000"
android:repeatCount="0"
android:fillAfter="true" />
<alpha
android:fromAlpha="2.0"
android:toAlpha="0.0"
android:duration="2000"
android:repeatCount="0"
android:startOffset="8000"
android:fillAfter="true" />
</set>
You are adding two separate animation. That is why they are intervaling.
As a beginner, I recommend getting into the habit of making animations (and really all resources possible) using xml. It is much more verbose and it is easier to change resources later on (as well as allowing you to automatically change resources at run time based on screen size, language, etc). Also get into a habit of really exhausting all android widgets before implementing something custom.
As far as a animation resource, look at the hyperspace_jump.xml
example at animation resources.
For view transitions i would normally recommend a ViewFlipper. However, since you want custom transitions, you may need to go down a level and use the ViewnAnimator. I understand you want to cycle through animations, but first get this working for one animation. I think this could still work with ViewFlipper, which would look something like this:
<ViewFlipper
android:id="@+id/VF"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inAnimation="@anim/yourFirstAnimation
android:flipInterval="@integer/flip_interval_time">
<ImageView
android:id="@+id/slide_1"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/slide_2"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</ViewFlipper>
onCreate(Bundle b) {
setContentView(R.layout.main);
mVF = (ViewFlipper) findViewById(R.id.VF);
mVF.startFlipping();
}
Then when you want to cycle through animations: Set your flipInterval to 0 (i think) and do like you did with the OnAnimationEnd event:
public void onAnimationEnd(Animation animation) {
Animation an = myAnimationContainer.getRandomAnimation();
mVF.setInAnimation(an);
mVF.showNext();
}
You shouldn't need to synchronize the flipInterval time, since this time really just depends how long the animation is.
精彩评论