ViewSwitcher代表了视图切换组件,它本身继承了FrameLayout,因此可以将多个View层叠在一起,每次只显示一个组件。当程序控制从一个View切换到另一个View时,ViewSwitcher支持指定动画效果。
为了给ViewSwitcher添加多个组件,一般通过调用ViewSwitcher的setFactory(ViewSwitcher.ViewFactory) 方法为之设置ViewFactory,并由该ViewFactory为之创建View即可。
最终实现的效果如下:
那就话不多说,上代码:
public class Activity137 extends Activity {
// 定义每个屏幕显示的应用程序数
public static final int NUMBER_PER_SCREEN = 12;
// 保存系统所有应用程序的List集合
private List<DataItem> items = new ArrayList<>();
private int screenNo = -1;
private int screenCount = 0;
private ViewSwitcher switcher;
private LayoutInflater inflater;
// 该BaseAdapter负责为每屏幕显示的View提供列表项
private BaseAdapter adapter = new BaseAdapter() {
@Override
public int getCount() {
// 如果当前是最后一屏,且应用程序的数量不足铺满一个屏幕
if (screenNo == screenCount - 1 && items.size() % NUMBER_PER_SCREEN != 0) {
return items.size() % NUMBER_PER_SCREEN;
} else {
return NUMBER_PER_SCREEN;
}
}
@Override
public DataItem getItem(int position) {
// 根据screenNo计算第position个列表项的数据
return items.get(screenNo * NUMBER_PER_SCREEN + position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 获取指定位置的视图
View view;
ViewHolder viewHolder;
if (convertView == null) {
view = inflater.inflate(R.layout.labelicon, null);
ImageView icon = view.findViewById(R.id.icon);
TextView label = view.findViewById(R.id.label);
viewHolder = new ViewHolder(icon, label);
// 将viewHolder和view关联绑定,可以避免重复创建和查找视图
view.setTag(viewHolder);
} else {
view = convertView;
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.imageView.setImageDrawable(getItem(position).drawable);
viewHolder.textView.setText(getItem(position).dataName);
return view;
}
};
// 代表应用程序的内部类
public static class DataItem {
// 应用程序名称
String dataName;
// 应用程序图标
Drawable drawable;
public DataItem(String dataName, Drawable drawable) {
this.dataName = dataName;
this.drawable = drawable;
}
}
public static class ViewHolder {
ImageView imageView;
TextView textView;
public ViewHolder(ImageView imageView, TextView textView) {
this.imageView = imageView;
this.textView = textView;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout137);
inflater = LayoutInflater.from(this);
// 创建一个包含40个元素的List集合,用于模拟包含40个应用程序
for (int i = 0; i < 40; i++) {
String label = i + "";
Drawable icon = getResources().getDrawable(R.mipmap.ic_launcher, null);
items.add(new DataItem(label, icon));
}
// 计算应用程序所占的总屏幕数
screenCount = items.size() / NUMBER_PER_SCREEN == 0 ?
items.size() / NUMBER_PER_SCREEN : items.size() / NUMBER_PER_SCREEN + 1;
switcher = findViewById(R.id.viewSwitcher);
switcher.setFactory(new ViewSwitcher.ViewFactory() {
@Override
public View makeView() {
return inflater.inflate(R.layout.slidelistview, null);
}
});
// 页面加载的时候显示第一屏
next(null);
}
public void next(View view) {
if (screenNo < screenCount - 1) {
screenNo++;
// 为ViewSwitcher组件显示过程设置动画
switcher.setInAnimation(this, R.anim.slide_in_right);
// 设置隐藏过程的动画
switcher.setOutAnimation(this, R.anim.slide_out_left);
// 控制下一屏将要显示的GridView对应的Adapter
((GridView) switcher.getNextView()).setAdapter(adapter);
// 显示下一屏
switcher.showNext();
}
}
public void pre(View view) {
if (screenNo > 0) {
screenNo--;
// 为ViewSwitcher组件显示过程设置动画
switcher.setInAnimation(this, R.anim.slide_in_left);
// 设置隐藏过程的动画
switcher.setOutAnimation(this, R.anim.slide_out_right);
// 控制上一屏将要显示的GridView对应的Adapter
((GridView) switcher.getNextView()).setAdapter(adapter);
// 显示上一屏
switcher.showPrevious();
}
}
}
主界面布局——layout137:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="500dp">
<ViewSwitcher
android:id="@+id/viewSwitcher"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Button
android:id="@+id/bt_pre"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginBottom="8dp"
android:onClick="pre"
android:text="<"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/bt_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginBottom="8dp"
android:onClick="next"
android:text=">"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
列表项组件布局——labelicon:
<?xml version="1.0" encoding="UTF-8" ?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:orientation="vertical"
android:padding="10dp">
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center" />
</LinearLayout>
每个屏显示应用程序的布局——slidelistview:
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="4" />
动画资源:
slide_in_right:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 设置从右边拖进来的动画
android:duration指定动画持续时间 -->
<translate
android:duration="@android:integer/config_mediumAnimTime"
android:fromXDelta="100%p"
android:toXDelta="0" />
</set>
slide_out_left:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 设置从左边拖出去的动画
android:duration指定动画持续时间 -->
<translate
android:duration="@android:integer/config_mediumAnimTime"
android:fromXDelta="0"
android:toXDelta="-100%p" />
</set>
slide_in_left:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 设置从右边拖进来的动画
android:duration指定动画持续时间 -->
<translate
android:duration="@android:integer/config_mediumAnimTime"
android:fromXDelta="-100%p"
android:toXDelta="0" />
</set>
slide_out_right:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 设置从右边拖进来的动画
android:duration指定动画持续时间 -->
<translate
android:duration="@android:integer/config_mediumAnimTime"
android:fromXDelta="0"
android:toXDelta="100%p" />
</set>
因为刚开始做相关的工作,理解经常出现错误,欢迎指摘。
日拱一卒,共同进步!