Android实战开发之引导页面
前言
本篇文章主要介绍了引导页面的设计与制作,引导页面的方法有很多种,我们采用ViewPager来实现。图片资源本篇文章从服务器获取的,当然如果没有服务器,也可以使用引用的资源图片。
提示:本篇文章不过多讲解Android的一些基础知识,只讲解实现过程与思路,后续将会通过链接的方式去陆续补充完整。敬请期待……
一、概述
- 使用ViewPager来实现引导页面的滑动效果
- ViewPager的实现需要适配器(Adapter)和数据源(List<View>)
- Adapter的作用是将数据源与ViewPager进行适配调节
注:List<view>是用于“打包多个”View(即视图,或者说布局),而每一个View又承载了一个图片控件用于图片的显示。
二、操作步骤
1.操作准备
- 新建包两个包activity和adapter用于文件分类
- 在activity和layout目录下分别创建文件activity_guide.xml和GuideActivity.java文件
- 在activity_guide.xml布局中添加ViewPager控件用来实现布局切换,添加三个View控件作为圆点显示引导页面位置
- 在adapter下新建文件ViewPagerAdapter.java
- 在layout下新建三个文件layout_guide01.xml、layout_guide02.xml、layout_guide03.xml三个布局文件并分别添加三个ImageView控件用于展示图片
- 在drawable文件目录下创建view_true.xml和view_false文件并使用shape绘画出两个不同颜色的圆,用于标识选中和未选中状态(也可以使用selector选择器这里不做讲解)
2.初始化
- 在GuideActivity.java中初始化控件、布局、数据
- 我们使用三张图片来作为引导页面,所以需要初始化三个布局、三个圆点、
三个图片(布局、圆点和图片的数量一定是统一的)。 - 这里我们将布局、图片和圆点控件用数组来声明,同时固定按顺序来声明一个int类型标识id的数组。
private View[] views;
private final int[] viewsId = {
R.layout.layout_guide01,
R.layout.layout_guide02,
R.layout.layout_guide03
};
private ImageView[] imageViews;
private final int[] imageViewsId = {
R.id.imageView,
R.id.imageView2,
R.id.imageView3
};
private View[] circleViews;
private final int[] circleViewsId = {
R.id.view,
R.id.view2,
R.id.view3
};
- 控件的初始化时,我们可以使用遍历数组的方式进行循环初始化(从下标为0开始
遍历,小于页面(图片)控件数组的长度—>取决于对应Id(layout)数组的长 度,这样写的最大好处在于更改时只需要对Id(layout)数组进行修改,便于维护)
layoutInflater = getLayoutInflater();
listView = new ArrayList<>();
viewpager = findViewById(R.id.viewPager);
views = new View[viewsId.length];
circleViews = new View[circleViewsId.length];
imageViews = new ImageView[imageViewsId.length];
for(int i = 0;i<3;i++){
views[i] = layoutInflater.inflate(viewsId[i],null,false);
circleViews[i] = findViewById(circleViewsId[i]);
imageViews[i] = views[i].findViewById(imageViewsId[i]);
listView.add(views[i]);
}
注:这里我们使用LayoutInferlater.inferlater方法(传入layout和null参数即 可)动态加载布局,也就是初始化,使用前需要实例化LayoutInferlate对象。 实例化List调用add方法传入View参数来初始化数据
3、适配器设置
public class ViewPagerAdapter extends PagerAdapter {
@Override
public int getCount() {
return listView.size();
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
container.addView(listView.get(position));
return listView.get(position);
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView(listView.get(position));
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
}
- 添加构造器,指定List<View>参数,用于实例化时传递List<View>数据
public ViewPagerAdapter(List<View> viewList){
this.listView = viewList;
}
- 实例化ViewPagerAdapter,调用写好的Adapter构造器传入初始化好的List
数据源,调用ViewPager的setAdapter方法将ViewPagerAdapter放入
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(listView);
viewpager.setAdapter(viewPagerAdapter);
3、圆点的滑动事件
- 这里我们调用ViewPager的滑动监听方法addOnPageChangeListener并重写onpageScrolled方法(需要实现三个基本方法其他两个不做过多讲解),其中position参数表示位置int类型,positionOffset参数表示位置偏移量float类型,positionOffsetPixels参数表示像素位置偏移量int类型。这里我们只需要position参数。
viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@SuppressLint("UseCompatLoadingForDrawables")
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
for(int i = 0;i<views.length;i++){
if(position == i){
circleViews[i].setBackground(getDrawable(R.drawable.circle_background_true));
}else{
circleViews[i].setBackground(getDrawable(R.drawable.circle_background_false));
}
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
注: 当处于第一张引导页面的时候,此时position的值为0,圆点的状态为选中状态。反之如果不是第一张页面,position的值不为0且圆点为未选中状态。我们使用 if else来进行判断,我们有三个引导页面(即三个圆点),因此我们需要重复三次 操作,我们利用for循环来执行(循环3次)。设置圆点选中和未选中我们调用的是setBackground方法参数为Drawable,因此我么需要调用getDrawable方法然后传入int类型的资源(即R.drawable.XXXX,来引用资源)
4、通过ApI获取图片资源并设置
- 首先创建子线程(网络请求是耗时任务需要在子线程中执行)获取图片的Json数据,我们调用封装好的requestGet方法请求json数据
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
JSONArray jsonArray = null;
String uri = null;
bitmaps = new Bitmap[imageViews.length];
String address = "http://124.93.196.67:8080";
String inface = "/prod-api/api/rotation/list?pageNum=1&pageSize=3";
String json = RequestUtil.requestGet(address+inface);
});
thread.start();
- 然后解析json数据获取到rows对应的以json为元素的数组,将其强制转换为JSONArray对象,然后通过JSONArray的get方法传入数组下标来读取对应的图片json数据,然后再次解析json对象获取到advImg对应的值,将这个值拼接到服务器地址即可获得图片的地址,再通过这个url调用写好的getImageBitmap方法将url地址转换为Bitmap对象
JSONObject jsonObject = new JSONObject(json);
JSONArray jsonArray = (JSONArray) jsonObject.opt("rows");
for(int i = 0;i<jsonArray.length();i++){
String advImg = jsonArray.get(i).toString();
JSONObject jsonObject1 = new JSONObject(advImg);
uri = jsonObject1.opt("advImg").toString();
String url = address + uri;
bitmaps[i] = RequestUtil.getImageBitmap(url);
}
- 最后切换到主线程调用Image的setImageBitmap方法设置图片
runOnUiThread(new Runnable() {
@Override
public void run() {
for(int i =0;i<imageViews.length;i++){
imageViews[i].setImageBitmap(bitmaps[i]);
}
}
});
注:关于JSONArray对象数据的读取,和Bitmap位图的设置同样采用数组遍历的方法。这里的网络请求封装和通过url获取图片的Bitmap不做讲解。
5、创建弹窗用于IP地址和端口号的保存与修改
- 自定义弹窗的建立需要先自定义一个弹窗的布局文件alertdialog.xml
- 首先我们需要实例化AlertDialog.Builder对象并传入上下文Context
调用LayoutInflater.inflater方法动态加载布局,再AlertDialog.Builder对象的setView、setTitl等方法来引入布局和基本设置,最后分别调用AlertDialog.Builder对象的create和show方法来创建展示弹窗,最终初始化控件就可以对控件进行设置
AlertDialog.Builder builder = new AlertDialog.Builder(GuideActivity.this);
View alertDialogView = layoutInflater.inflate(R.layout.alertdialog,null);
builder.setView(alertDialogView).setTitle("网络设置");
builder.create();
Dialog dialog = builder.show();
EditText ipEt = alertDialogView.findViewById(R.id.editTextTextPersonName2);
EditText portEt = alertDialogView.findViewById(R.id.editTextTextPersonName3);
Button saveBt = alertDialogView.findViewById(R.id.button5);
Button cancelBt = alertDialogView.findViewById(R.id.button6);
cancelBt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dialog.dismiss();
Toast.makeText(GuideActivity.this,"修改成功!",Toast.LENGTH_SHORT).show();
}
});
saveBt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String ip = ipEt.getText().toString().trim();
String port = portEt.getText().toString().trim();
sharedPreferences02 = getSharedPreferences("socket",MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences02.edit();
editor.putString("ip",ip);
editor.putString("port",port);
editor.apply();
dialog.dismiss();
Toast.makeText(GuideActivity.this,"保存成功!",Toast.LENGTH_SHORT).show();
}
});
注:保存和修改IP和端口号的方法一样(Shared Preferences数据覆盖机制),SharedPreferences的使用需要声明SharedPreferences和SharedPreferences.Editor对象并分别调用getSharedPregerences方法传入String类型的name和MODE_PRIVATE和SharedPreferences.edit方法。最后调用SharedPereferences.Editor的putSting方法以键值对形式存储数据,最终调用Shared Preferences.Editor的apply方法提交保存(commit方法也可,但在一些情况下会出现问题,不建议使用)
三、总结
以上便是引导页面的设计与制作,猿友们可以根据实际需求和实际情况随机应变。有什么问题欢迎留言,一起学习进步哦~
|