android实现上下滚动的TextView
一 说明
这里重要应用类 autotextview,这是一个自定义的类,继承至textswitcher,下面临 autotextview类做简要说明:
1. 该类应用的重点,在于设置两个动画, setinanimation(...) 和 setoutanimation(...),分离是文字进入的动画和文字退出的动画;
2. 类中定义了一个外部类-rotate3danimation,重要靠该类实现文字进出动画,该外部类继承至animation。说来偶合,这个恰好是在apidemo中看到了,自定义animation我还是第一次应用,动画逻辑均在void applytransformation(float interpolatedtime, transformation t)中实现,代码相当锋利,我在原来的基础上,更改了一下,实现了上述的效果,
二 代码部分:
1.autotextview.java
package com.example.animtextview;
import android.content.context;
import android.content.res.typedarray;
import android.graphics.camera;
import android.graphics.matrix;
import android.util.attributeset;
import android.view.gravity;
import android.view.view;
import android.view.animation.accelerateinterpolator;
import android.view.animation.animation;
import android.view.animation.transformation;
import android.widget.textswitcher;
import android.widget.textview;
import android.widget.viewswitcher;
public class autotextview extends textswitcher implements
viewswitcher.viewfactory {
private float mheight;
private context mcontext;
//minup,moutup分离构成向下翻页的进出动画
private rotate3danimation minup;
private rotate3danimation moutup;
//mindown,moutdown分离构成向下翻页的进出动画
private rotate3danimation mindown;
private rotate3danimation moutdown;
public autotextview(context context) {
this(context, null);
// todo auto-generated constructor stub
}
public autotextview(context context, attributeset attrs) {
super(context, attrs);
// todo auto-generated constructor stub
typedarray a = context.obtainstyledattributes(attrs, r.styleable.auto3d);
mheight = a.getdimension(r.styleable.auto3d_textsize, 36);
a.recycle();
mcontext = context;
init();
}
private void init() {
// todo auto-generated method stub
setfactory(this);
minup = createanim(-90, 0 , true, true);
moutup = createanim(0, 90, false, true);
mindown = createanim(90, 0 , true , false);
moutdown = createanim(0, -90, false, false);
//textswitcher重要用于文件切换,比如 从文字a 切换到 文字 b,
//setinanimation()后,a将执行inanimation,
//setoutanimation()后,b将执行outanimation
setinanimation(minup);
setoutanimation(moutup);
}
private rotate3danimation createanim(float start, float end, boolean turnin, boolean turnup){
final rotate3danimation rotation = new rotate3danimation(start, end, turnin, turnup);
rotation.setduration(800);
rotation.setfillafter(false);
rotation.setinterpolator(new accelerateinterpolator());
return rotation;
}
//这里返回的textview,就是我们看到的view
@override
public view makeview() {
// todo auto-generated method stub
textview t = new textview(mcontext);
t.setgravity(gravity.center);
t.settextsize(mheight);
t.setmaxlines(2);
return t;
}
//定义动作,向下滚动翻页
public void previous(){
if(getinanimation() != mindown){
setinanimation(mindown);
}
if(getoutanimation() != moutdown){
setoutanimation(moutdown);
}
}
//定义动作,向上滚动翻页
public void next(){
if(getinanimation() != minup){
setinanimation(minup);
}
if(getoutanimation() != moutup){
setoutanimation(moutup);
}
}
class rotate3danimation extends animation {
private final float mfromdegrees;
private final float mtodegrees;
private float mcenterx;
private float mcentery;
private final boolean mturnin;
private final boolean mturnup;
private camera mcamera;
public rotate3danimation(float fromdegrees, float todegrees, boolean turnin, boolean turnup) {
mfromdegrees = fromdegrees;
mtodegrees = todegrees;
mturnin = turnin;
mturnup = turnup;
}
@override
public void initialize(int width, int height, int parentwidth, int parentheight) {
super.initialize(width, height, parentwidth, parentheight);
mcamera = new camera();
mcentery = getheight() / 2;
mcenterx = getwidth() / 2;
}
@override
protected void applytransformation(float interpolatedtime, transformation t) {
final float fromdegrees = mfromdegrees;
float degrees = fromdegrees + ((mtodegrees - fromdegrees) * interpolatedtime);
final float centerx = mcenterx ;
final float centery = mcentery ;
final camera camera = mcamera;
final int derection = mturnup ? 1: -1;
final matrix matrix = t.getmatrix();
camera.save();
if (mturnin) {
camera.translate(0.0f, derection *mcentery * (interpolatedtime - 1.0f), 0.0f);
} else {
camera.translate(0.0f, derection *mcentery * (interpolatedtime), 0.0f);
}
camera.rotatex(degrees);
camera.getmatrix(matrix);
camera.restore();
matrix.pretranslate(-centerx, -centery);
matrix.posttranslate(centerx, centery);
}
}
}
2. mainactivity.java
package com.example.animtextview;
import android.os.bundle;
import android.app.activity;
import android.view.view;
import android.view.view.onclicklistener;
import android.widget.button;
public class mainactivity extends activity implements onclicklistener {
private button mbtnnext;
private button mbtnprev;
private autotextview mtextview02;
private static int scount = 10;
@override
protected void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_main);
init();
}
private void init() {
// todo auto-generated method stub
mbtnnext = (button) findviewbyid(r.id.next);
mbtnprev = (button) findviewbyid(r.id.prev);
mtextview02 = (autotextview) findviewbyid(r.id.switcher02);
mtextview02.settext("hello world!");
mbtnprev.setonclicklistener(this);
mbtnnext.setonclicklistener(this);
}
@override
public void onclick(view arg0) {
// todo auto-generated method stub
switch (arg0.getid()) {
case r.id.next:
mtextview02.next();
scount++;
break;
case r.id.prev:
mtextview02.previous();
scount--;
break;
}
mtextview02.settext(scount%2==0 ?
scount+"aafirstaa" :
scount+"bbbbbbb");
system.out.println("geth: ["+mtextview02.getheight()+"]");
}
}
3. activity_main.xml
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:auto3d="http://schemas.android.com/apk/res/com.example.animtextview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<relativelayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<button
android:id="@+id/next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignparentleft="true"
android:layout_alignparenttop="true"
android:text="@string/next" />
<button
android:id="@+id/prev"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignparentright="true"
android:layout_alignparenttop="true"
android:text="@string/prev" />
</relativelayout>
<com.example.animtextview.autotextview
android:id="@+id/switcher02"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/holo_green_dark"
auto3d:textsize="30sp" />
</linearlayout>
代码中没写太多注释,不过结构还算清晰,应该不难看懂!
三 小结
我认为该控件实现的难点在于 动画文件的编写,即rotate3danimation中applytransformation(...)方法的实现,通过控制camara在y方向上挪动和在x方向上的旋转,从而造成上下翻滚的视觉感,然后将该值转换到matrix上,从而改变了参数(..,transformation t).有兴致的朋友可以直接改写该方法,便可失掉不同动画效果的textswitcher.