这篇文章是“全栈工程师移动开发实践”的系列教程的一部分,在讲解了服务端spring boot的基本使用后,我们来从头看看一款App开发的来龙去脉。
1.什么是引导页?
我们首次安装某个App的时候经常会看到图一的引导页,那么到底什么是引导页呢?所谓的引导页,从字面意思讲就是就是引导用户,目的是让用户学习app的使用方法,明确地指出app能为用户带来哪些价值,从而吸引用户。
2.引导页是不是必要的?
很多非专业的互联网公司,通常都会给自己的App设置引导页,对于他们而言,引导页就是标配,没有的话显得很low。事实上不是这样的,引导页应该根据app的人群定位,以及自身功能定位,结合用户体验,来决定是不是设置。目前的技术水平,很难有实现不了的需求,所以良好的用户体验是产品生存的根本所在。大部分优秀的App,基本上学习成本很低,用户看一眼基本就知道该怎么使用。因此,引导页不是每个app必须要做的,除了以下几个方面可以酌情考虑。
(1)App比较新颖,创新性很强,初次接触可能需要花时间去了解。这种情况下,就可以做个引导页,把App的独特之处介绍给用户,同时用简洁的文字或图片向用户介绍其功能,这是非常有必要的。
(2)App改版,使得老用户的使用习惯发生很大改变的情况下,需要像用户说明改动点,让用户更加容易切换到新的App。
(3)一些颠覆传统的操作方式,比如手势,左右手习惯问题,应该向用户交代清楚,以免引起误解,影响用户体验。
除了以上场景或者一些特殊情况,引导页对于App并没有多大影响,不要迷恋引导页,因地制宜。
3.手把手教你如何设置引导页
首先介绍一下ButterKnife,学习android开发一定使用过findViewById()和setonclicktListener(),尤其是控件对象比较多的时候,一坨一坨的代码真的是够够的了。ButterKnife通过java注解自动生成java代码的形式来完成工作,使用 @Bind注解并传入一个View ID,Butter Knife 就可以找到并且自动地对你的布局中的View进行转换并绑定到类成员上。
举例如下:
class ExampleActivity extends Activity {
@Bind(R.id.title)
TextView title;
@Bind(R.id.subtitle)
TextView subtitle;
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.example_layout);
ButterKnife.bind(this);
}
}
其次,设置引导页,一般都会使用到ViewPager。ViewPager是一个允许使用者左右滑动数据页面的布局管理器,可以通过一个PagerAdapter适配器来管理要显示的页面。我们来看看ViewPager的官方api的继承关系:
ViewPager继承自ViewGroup,是个容器类,内部可以嵌套其他View。
有了以上基础,我们开始设置引导页。
(1)添加布局文件:activity_guide.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="100dp"
android:orientation="horizontal" />
</RelativeLayout>
(2)ViewPager中的视图样式我们默认显示图片,所以定义PagerAdapter显示的样式的xml,activity_guide_item.xml
<?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:background="@color/white"
android:orientation="vertical">
<ImageView
android:id="@+id/guide_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:scaleType="center" />
</LinearLayout>
(3)新建GuideActivity ,设置四张引导页,分别对应guide_1,guide_2,guide_3,guide_4,同时选择当前页,下方的图标显示选中ic_indicators_selected,未选中显示ic_indicators_default。
/**
* 引导页
*/
public class GuideActivity extends BaseActivity {
private static final String TAG = GuideActivity.class.getSimpleName();
@Bind(R.id.viewpager)
ViewPager viewpager;
@Bind(R.id.indicator)
LinearLayout indicator;
private List<View> viewList;
private ImageView[] indicatorImgs;
private static final int GUIDE_PAGE_COUNT = 4;
private int[] imgResArr = new int[]{R.mipmap.guide_1, R.mipmap.guide_2, R.mipmap.guide_3, R.mipmap.guide_4};
public static void start(Context context) {
Intent intent = new Intent(context, GuideActivity.class);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_guide);
ButterKnife.bind(this);
super.onCreate(savedInstanceState);
}
@Override
public void initData() {
indicatorImgs = new ImageView[GUIDE_PAGE_COUNT];
viewList = new ArrayList<View>(GUIDE_PAGE_COUNT);
for (int i = 0; i < GUIDE_PAGE_COUNT; i++) {
View view = LayoutInflater.from(this).inflate(R.layout.activity_guide_item, null);
view.setBackgroundResource(R.color.white);
((ImageView) view.findViewById(R.id.guide_image)).setBackgroundResource(imgResArr[i]);
viewList.add(view);
indicatorImgs[i] = new ImageView(this);
if (i == 0) {
indicatorImgs[i].setBackgroundResource(R.mipmap.ic_indicators_selected);
} else {
indicatorImgs[i].setBackgroundResource(R.mipmap.ic_indicators_default);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(-2, -2);
layoutParams.setMargins(20, 0, 0, 0);
indicatorImgs[i].setLayoutParams(layoutParams);
}
indicator.addView(indicatorImgs[i]);
}
}
@Override
public void initTitle() {
}
public void setListener(){};
@Override
public void initView() {
viewpager.setAdapter(new PagerAdapter() {
@Override
public int getCount() {
return viewList.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(viewList.get(position));
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(viewList.get(position));
return viewList.get(position);
}
});
viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
setIndicator(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
public void setIndicator(int targetIndex) {
for (int i = 0; i < indicatorImgs.length; i++) {
indicatorImgs[i].setBackgroundResource(R.mipmap.ic_indicators_selected);
if (targetIndex != i) {
indicatorImgs[i].setBackgroundResource(R.mipmap.ic_indicators_default);
}
}
}
}
到这里,App引导页全部制作完成,大家可以根据需求添加不同的样式,就是这么简单哦,附上效果图:
如果您喜欢我们的文章,点赞就好,您的认可是我分享的最大动力。