TextSwitcher与ViewSwitcher学习笔记

TextSwitcherViewSwitcher是什么,有什么用呢?

其实大家从名字就可以看出来其大概意思,TextSwitcher是用来切换文本显示的,而ViewSwitcher是用来切换视图显示的,实际上他们也的确是用来做这个的,只不过他们在切换视图显示的时候允许添加切换的动画效果。TextSwitcher其实也是ViewSwitcher的子类实现。

TextSwitcher使用

我们先来看看TextSwitcher的用法:

关键布局代码如下:

1
2
3
4
5
6
7
8
9
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="change"/>
<TextSwitcher
android:id="@+id/switcher"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

Java代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//设置显示Text文本的View创建工厂
//这是通过代码的方式创建显示文本的视图,也可以直接在布局中设置显示文本的视图,这个在讲ViewSwitcher的用法的时候再说
mTextSwitcher.setFactory(new ViewSwitcher.ViewFactory() {
@Override
public View makeView() {
TextView t = new TextView(TextSwitcherActivity.this);
t.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
t.setTextAppearance(TextSwitcherActivity.this, android.R.style.TextAppearance_Large);
return t;
}
});
Animation in = AnimationUtils.loadAnimation(this,
android.R.anim.fade_in);
Animation out = AnimationUtils.loadAnimation(this,
android.R.anim.fade_out);
mTextSwitcher.setInAnimation(in);//设置文本出现动画
mTextSwitcher.setOutAnimation(out);//设置文本消失动画
mTextSwitcher.setCurrentText(String.valueOf(mCount));//设置初始值,初始值不显示动画
int mCount = 0;
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCount++;
mTextSwitcher.setText(String.valueOf(mCount));//更新文本显示值,会出现动画
}
});

当你点击界面上的按钮的时候,会不断的更新TextSwitcher的显示值,而在更新过程中文本会出现一个淡入淡出的效果,这个效果就是通过动画产生的。

ViewSwitcher使用

接着我们再来看看ViewSwitcher的使用
布局代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="change"/>
<ViewSwitcher
android:id="@+id/viewSwitcher"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="300dp"
android:layout_height="300dp"
android:src="@drawable/image1"/>
<ImageView
android:layout_width="300dp"
android:layout_height="300dp"
android:src="@drawable/image2"/>
</ViewSwitcher>

上面的布局中我们给ViewSwitcher添加了两个子视图,注意这里只能添加两个直接子视图,否则初始化会出现异常,至于原因后面接着说。前面说过TextSwitcher也可以通过布局设置文本显示视图,它的设置方式与ViewSwitcher其实也是一样的。

ok,接着上Java代码

1
2
3
4
5
6
7
8
9
10
11
12
13
//因为我们已经通过布局的方式设置了要切换的视图,所以就不需要再设置Factory去生成切换视图了
Animation slide_in_left = AnimationUtils.loadAnimation(this,
android.R.anim.slide_in_left);
Animation slide_out_right = AnimationUtils.loadAnimation(this,
android.R.anim.slide_out_right);
mViewSwitcher.setInAnimation(slide_in_left);//设置图片出现动画
mViewSwitcher.setOutAnimation(slide_out_right);//设置图片消失动画
mButton2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mViewSwitcher.showNext();
}
});

上面就是ViewSwitcher的使用方式,其实用起来还是很简单的。通过自定义动画,我们可以为两个View切换时添加更多漂亮有趣的动画效果

使用场景

在Android开发中视图切换显示还是很常见的,比如应用加载数据时显示加载动画视图数据视图隐藏,而加载成功后加载动画视图隐藏数据视图显示,这个场景使用ViewSwitcher来实现应该会更简单,更方便。

源码探究

  • 前面说到过ViewSwitcher只能存在两个直接子视图,否则会初始化失败,这是为什么呢?通过源码我们可以找到答案
1
2
3
4
5
6
7
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
if (getChildCount() >= 2) {
throw new IllegalStateException("Can't add more than 2 views to a ViewSwitcher");
}
super.addView(child, index, params);
}
  • 在前面ViewSwitcher的使用中我们点击按钮的时候直接调用了mViewSwitcher.showNext();,既然只能有两个子视图,那我们每次点击都showNext()怎么会没出现越界异常呢?ok,我们还是看看源码中是怎么实现的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@android.view.RemotableViewMethod
public void showNext() {
setDisplayedChild(mWhichChild + 1);
}
@android.view.RemotableViewMethod
public void setDisplayedChild(int whichChild) {
mWhichChild = whichChild;
if (whichChild >= getChildCount()) {
mWhichChild = 0;
} else if (whichChild < 0) {
mWhichChild = getChildCount() - 1;
}
boolean hasFocus = getFocusedChild() != null;
// This will clear old focus if we had it
showOnly(mWhichChild);
if (hasFocus) {
// Try to retake focus if we had it
requestFocus(FOCUS_FORWARD);
}
}

通过上面的实现我们可以看到当其显示的child索引出现越界之后,会自动的进行循环显示,这也是为什么一直调用showNext()没出现越界异常的原因

切换原理

我们再来看看其切换显示过程中视图的显示和隐藏及动画是如何实现的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void showOnly(int childIndex, boolean animate) {
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (i == childIndex) {
if (animate && mInAnimation != null) {
child.startAnimation(mInAnimation);
}
child.setVisibility(View.VISIBLE);
mFirstTime = false;
} else {
if (animate && mOutAnimation != null && child.getVisibility() == View.VISIBLE) {
child.startAnimation(mOutAnimation);
} else if (child.getAnimation() == mInAnimation)
child.clearAnimation();
child.setVisibility(View.GONE);
}
}
}

上面的代码实现也很简单,当显示指定索引的child时,将其设置为可见并执行mInAnimation,其他视图在设置为不可见并执行mOutAnimation动画

Factory作用原理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void setFactory(ViewFactory factory) {
mFactory = factory;
obtainView();
obtainView();
}
private View obtainView() {
View child = mFactory.makeView();
LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp == null) {
lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
addView(child, lp);
return child;
}

通过源码实现我们可以知道mTextSwitcher.setFactory(mFactory)设置完成之后,ViewSwitcher会立刻生成两个视图作为其子视图作为切换显示用。

示例代码在这里:https://github.com/huyongli/AndroidDemo


原创文章,本文采用知识共享署名 2.5(中国大陆许可协议)进行许可,欢迎转载,但转载请注明来自ittiger.cn,并保证转载后文章内容的完整性。本人(laohu)保留所有版权相关权利。



评论