《****教学软件》Android tabLayout配合viewPage制作练习题界面
前言
最近开发一款学习软件,练手作品,我暂且命名《****教学软件》。本人初开发android软件,边学习边制作边记录,为以后不踩坑做一下记录。在做这个软件的过程中,会不断记录。后期会分享一下我做的软件包。
由于边开发边记录,只展示比较重要的部分代码,所以代码可能比较杂乱。大家觉得代码不正确或不清晰的,可以在讨论留言,大家一起学习,一起进步
借鉴到学习通的界面,我打算做一个差不多的,左图为学习通答题。右图为我自己做的初期效果图。
由于数据库是access转sqlite做成的,没有转码,所以乱码。由于功能演示用,重点不在界面。所以不纠结了。
前期准备
基本数据准备
前期把需要展示的数据准备好,我是查找数据库导出,我以ArrayLIist配合HashMap存储数据。
//单选题数据,我做了多选题,判断题,填空题,现在只展示单选题
ArrayList singles = new ArrayList<Map<String, Object>>();
准备一系列view
题目嘛,都是文字,耗内存小,我为了省事,就先把需要展示的view添加进ArrayList数组中。如果不想这样,后面还会说另一种加载view的方法。
此处展示添加view进list的方法
public ArrayList<View> setViewArray() {
views = new ArrayList<View>();
for (int i = 0; i < sum; i++) {
View view = lf.inflate(R.layout.test_item_activity_items, null);
LinearLayout layout = view.findViewById(R.id.layout);
TextView question = view.findViewById(R.id.question);
TextView answer = view.findViewById(R.id.answer);
TextView description = view.findViewById(R.id.description);
//question绑定//answer区控件设置,四个类型,四个设置
if (i < singles.size()) {
question.setText((String) singles.get(i).get("question"));
setSingles(layout, i);
true_answers[i] = (String) singles.get(i).get("answer");
descriptions[i] = (String) singles.get(i).get("description");
answer.setText((String) singles.get(i).get("answer"));
description.setText((String) singles.get(i).get("description"));
} else if (i < (singles.size() + multiple.size())) {
int ii = i - singles.size();
question.setText((String) multiple.get(ii).get("question"));
setMultiple(layout, i);
true_answers[i] = (String) multiple.get(ii).get("answer");
descriptions[i] = (String) multiple.get(ii).get("description");
answer.setText((String) multiple.get(ii).get("answer"));
description.setText((String) multiple.get(ii).get("description"));
} else if (i < (singles.size() + multiple.size()) + judge.size()) {
int ii = i - singles.size() - multiple.size();
question.setText((String) judge.get(ii).get("question"));
setJudge(layout, i);
true_answers[i] = (String) judge.get(ii).get("answer");
descriptions[i] = (String) judge.get(ii).get("description");
answer.setText((String) judge.get(ii).get("answer"));
description.setText((String) judge.get(ii).get("description"));
} else if (i < (singles.size() + multiple.size()) + judge.size() + fill.size()) {
int ii = i - singles.size() - multiple.size() - judge.size();
question.setText((String) fill.get(ii).get("question"));
setFill(layout, i);
true_answers[i] = (String) fill.get(ii).get("answer");
descriptions[i] = (String) fill.get(ii).get("description");
answer.setText((String) fill.get(ii).get("answer"));
description.setText((String) fill.get(ii).get("description"));
}
views.add(view);
}
return views;
}
具体实现
定义TestAdapter类
我定义了一个adapter类
class TestAdapter extends PagerAdapter {
ArrayList<View> views;
public String[] ins;
@Override
public int getCount() {
return views.size();
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
//这是刚才提到的另一种方法get view;
// View view = LayoutInflater.from(container.getContext()).inflate(R.layout.test_item_activity_items, null);
// //container.addView(view);
// LinearLayout layout = view.findViewById(R.id.layout);
// TextView text = view.findViewById(R.id.question);
// if (position<singles.size()){
// text.setText((String)singles.get(position).get("question"));
// }else if (position<singles.size()+multiple.size()){
// text.setText((String)multiple.get(position-singles.size()).get("question"));
// }
// if (container.getChildAt(position)==null){
// container.addView(view);
// }else{
// return false;
// }
//
// return view;
//这是我想多了
// if (container.getChildAt(position) == null) {
// container.addView(views.get(position));
// } else {
// return false;
// }
container.addView(views.get(position));
return views.get(position);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(views.get(position));
}
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return ins[position];
}
}
这是刚才提到的另一种方法get view;,viewPage滑动的时候加载view,如果view复杂,把view加载list耗费时间比较长,可以用这样的方法。我没试过,估计可行,如果有小伙伴懂得话,指点一二。
// View view = LayoutInflater.from(container.getContext()).inflate(R.layout.test_item_activity_items, null);
// //container.addView(view);
// LinearLayout layout = view.findViewById(R.id.layout);
// TextView text = view.findViewById(R.id.question);
// if (position<singles.size()){
// text.setText((String)singles.get(position).get("question"));
// }else if (position<singles.size()+multiple.size()){
// text.setText((String)multiple.get(position-singles.size()).get("question"));
// }
// if (container.getChildAt(position)==null){
// container.addView(view);
// }else{
// return false;
// }
//
// return view;
这里有一些要注意的地方;这是我想多了,因为刚开始想的是以为pageradapter的destroyItem方法在切换下一个页面,会把以前老的view删除掉,用户之前的选择按钮的状态就没有了。但是我想多了,我刚开始不是加view到list嘛,用户操作view的单选按钮,按钮状态也会保存在view中。adapter加载view是从我的list中得到,还会保存的。下面的代码多次一举
//这是我想多了
// if (container.getChildAt(position) == null) {
// container.addView(views.get(position));
// } else {
// return false;
// }
adapter的这个方法一定要加,不然会报错
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(views.get(position));
}
adapter这个方法也加上,设置tabitem的标题字,不加,不显示item
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return ins[position];
}
OnCreate()方法
这是在onCreate()中实例化viewPage,tabLayout
viewPager = findViewById(R.id.viewpager);
TabLayout tabs = findViewById(R.id.tabss);
submit = findViewById(R.id.submit);
TestAdapter adapter = new TestAdapter();
adapter.views = setViewArray();//使用setViewArray()方法获得view数组
ins = new String[sum];//这是要设置的tabitem标题名字
for (int i = 0; i < sum; i++) {
//tabs.addTab(tabs.newTab());
ins[i] = String.valueOf(i + 1);
}
adapter.ins = ins;
viewPager.setAdapter(adapter);
tabs.setupWithViewPager(viewPager, false);
提交按钮的设置
submit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
for (int i = 0; i < sum; i++) {
//设置正确答案和错误答案显示的效果
if (user_answers[i].compareToIgnoreCase(true_answers[i]) == 0) {
//这里省略
}
//设置每一个view的两个text可见
TextView text1 = (TextView) views.get(i).findViewById(R.id.answer);
text1.setVisibility(View.VISIBLE);
text1.setText("您的答案是:" + user_answers[i] + " 正确答案是:" + true_answers[i]);
TextView text2 = (TextView) views.get(i).findViewById(R.id.description);
text2.setVisibility(View.VISIBLE);
text2.setText("解析: \n" + descriptions[i]);
//调整好view之后,需要重新适配器
TestAdapter adapter = new TestAdapter();
adapter.views = views;
adapter.ins = ins;
viewPager.setAdapter(adapter);
}
}
});
后期美化
先挖个坑,这个等我APP弄出来在添加吧。
总结
1、我觉得view的PageAdapter的数据最好是ArrayList<View>,省事,不闹心。
2、tabitem的标题不显示的原因可能是adapter中的getPageTitle()没覆写。