IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 安卓场景开发(一) 引导页面 -> 正文阅读

[移动开发]安卓场景开发(一) 引导页面

一 引导页

效果图:
ezgif.com-video-to-gif.gif

1.1 什么是引导页?

在网络上做了一些查询,没有找到引导页的官方或权威定义,决定从其字面意思来进行推论。所谓引导页,就是引导用户学习app用法或了解app作用的页面,其核心在于“引导”二字。在此情况下,若一个号称引导页的东西不能达到让用户学习app的用法,或了解app相关,都不能使真正意义上的引导页。

1.2 为什么要用引导页?

到底为什么多数app都会在很多情况下增加引导页呢?个人认为原因在于以下几点:

  1. 受传统pc时代软件说明书的影响。pc时代的一个软件,用户往往不知道如何操作,甚至需要上专门的课程学习某个软件才行,比如office系列。因此,每个软件一旦销售必然配备使用说明书,以帮助用户学习。但是,在移动互联网时代,对于轻量级的app使用说明书太重了,所以使用了引导页这种轻量级的方式。
  2. app设计者假设用户会希望了解这个app到底是个什么东西?能干什么?怎么用?所以要做引导页来回答用户内心的这些问题。
  3. app设计者看到别人有,没有多想,觉得自己的app也应该做一个。

然而,现实中的情况是什么呢?

  1. 在这个注重极致用户体验的时代,绝大多数app的设计已经可以做到不证自明的阶段。用户一看就知道这玩意儿应该怎么用,能用来干什么。
  2. 即使用户对某个app没有任何认知,在下载这个app之前也肯定会有一些前置了解来帮助自己决定是否有必要下载(产品狗除外,什么app都会划拉下来看看),或者道听途说,或者朋友推荐等等。因此,引导页能够告诉用户的多数情况下是他已经知道的。
  3. 即使还需要深入了解的app(甚至手机系统这么复杂的玩意儿),多数的用户还是会采取自我探索的方式来学习如何使用。而这种学习方式对于成长在互联网时代的90、00、10后更是如此。(我四岁的侄女不识字照样可以用手机拍照、看动画片)。
  4. 用户打开app的目的是使用其功能来完成任务,往往不希望有任何障碍。因此,真正有耐心看完引导页的用户很少,多数会直接快速滑动跳过。即使引导页做得再好。
  5. 很多公司其实已经注意到了这种情况,所以他们在引导页上添加了“跳过”按钮,来防止用户对翻好几页引导页而反感。

因此,从某种意义上来说,引导页的存在其实是一个大家觉得存在没什么不对,但是却又没太多人用的这么一个东西。
那么,是不是不需要做引导页了呢?我想说的是:对,不需要做引导页了。除非:

  1. 你的app是一个全新概念的app,是市面上没有人有过的玩法。即使用户能够从各种途径了解到相关信息,但也无法完全理解你所想要传达的信息。你有不说就死的理由。此种情况下,你可以做引导页,也许能够让部分用户加深对app的了解。
  2. 你的app增加了非常大块的功能,大到可能改变整个app的使用场景,值得你重点强调。就像发布一个全新的app一样。
  3. 你的app新增加了非常重要的功能,但又无法在界面上重点展示(离线下载的控制),非常有必要向你的用户强调。
  4. 你的app使用了别人不曾用过的或用户难以想到的操作方式,同时又对使用app有重大影响,必须介绍。

1.3 效果图

file .png
file  (1).png

1.4 安卓的实现形式

Android的APP应用中最常用的 APP启动引导页 ,常见的4种引导项目方式:

  • splash
  • viewpage
  • viewflipper
  • scrollview

1.5 开源组件

  • Guideshow使你简单、快速的构建引导页。另外,你无须生成动态的gif图片就可使页面产生动画效果,如平移、渐变。项目地址:https://github.com/javajavadog/guideshow
  • 一个轻量级的viewpager指示器 ,类似于nexus5 启动器的效果。它可以自定义指示器上小圆点的样式和动画效果。可以用于引导页。项目地址:https://github.com/ongakuer/CircleIndicator

1.6 素材来源

1.7 注意点

  • 引导页一般是在用户第一次进入app时给用户的友好提示,包括介绍app的基本功能,最近更新的功能等等。因此只会初始化一次。
  • 目前市场上的app的引导页大部分都是采用ViewPager滑动的方式实现,每一个页面采用图片或者素材加图片的方式填充。

二 ViewPager实现引导页

2.1 ViewPage的介绍

  • ViewPager是v4包中的一个类。
  • ViewPager继承自ViewGroup,其实是一个容器。
  • ViewPager类似于ListView,也有自己的适配器,里面用来填充数据页面。
  • ViewPager一般和Fragment一起使用,它更方面的管理页面中Fragment的生命周期。

2.2 基本使用

  • 编写一个自定义Adapter继承PagerAdapter
  • 实现器基本方法

int getCount():返回显示多少个页面
boolean isViewFromObject(View view, Object object):判断初始化返回的Object是不是一个View对象
Object instantiateItem(ViewGroup container, int position):初始化显示的条目对象
void destroyItem(ViewGroup container, int position, Object object):销毁条目对象

  • 设置适配器

2.3 基本开发

  • 素材来自网络,侵权什么的请及时告知,谢谢。
  • 效果图:

image.png
image.png

2.3.1 首页布局编写

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                tools:context=".MainActivity">
  
  
  <androidx.viewpager.widget.ViewPager
                                       android:id="@+id/viewpager"
                                       android:layout_width="match_parent"
                                       android:layout_height="match_parent" />
  
  <TextView
            android:id="@+id/skip_home"
            android:textColor="@color/black"
            android:gravity="center"
            android:layout_alignParentEnd="true"
            android:layout_marginTop="10dp"
            android:layout_marginEnd="10dp"
            android:background="@drawable/loading"
            android:layout_width="40dp"
            android:textSize="12sp"
            android:layout_height="40dp"
            android:text="@string/skip_name"/>
  
  
  <LinearLayout
                android:layout_alignParentBottom="true"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:layout_margin="30dp"
                android:orientation="horizontal">
    
    <ImageView
               android:id="@+id/imageOne"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content" />
    
    <ImageView
               android:id="@+id/imageTwo"
               android:layout_marginRight="10dp"
               android:layout_marginLeft="10dp"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content" />
    
    <ImageView
               android:id="@+id/imageThree"
               android:layout_marginRight="10dp"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content" />
    
    
  </LinearLayout>
</RelativeLayout>

2.3.2 设配器编写

package com.shu.Adapter;

import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.viewpager.widget.PagerAdapter;

import java.util.List;

/**
* @Author shu
* @Version 1.0
* @Date: 2022/06/26/ 12:54
* @Description 引导页面适配器
**/
public class GuideViewPagerAdapter extends PagerAdapter {
    private List<View> views;
    
    public GuideViewPagerAdapter(List<View> views) {
        super();
        this.views = views;
    }
    
    
    
    /**
    * 返回显示多少个页面
    * @return
    */
    @Override
    public int getCount() {
        if (views != null) {
            return views.size();
        }
        return 0;
    }
    
    
    /**
    *判断初始化返回的Object是不是一个View对象
    * @param view
    * @param object
    * @return
    */
    @Override
    public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
        return view == (object);
    }
    
    /**
    * 销毁对象
    * @param container
    * @param position
    * @param object
    */
    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        container.removeView(views.get(position));
    }
    
    /**
    * 初始化对象
    * @param container
    * @param position
    * @return
    */
    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        (container).addView(views.get(position), 0);
        return views.get(position);
    }
    
}


2.3.3 引导页面编写

loading_view1.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="@mipmap/loading_03"
    android:gravity="center|bottom"
    android:orientation="vertical">

    <Button
        android:id="@+id/start_home"
        android:background="@drawable/btn_go"
        android:textColor="@color/white"
        android:layout_width="150dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="90dp"
        android:text="@string/home_name" />

</LinearLayout>

image.png

2.3.4 小圆圈样式编写

未选中:

<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid
        android:color="#03A9F4"/>
    <size
        android:width="5dp"
        android:height="5dp"/>
</shape>

选中:

<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid
        android:color="#040404"/>
    <size
        android:width="5dp"
        android:height="5dp"/>
</shape>

2.3.5 主要代码逻辑编写

package com.shu.Activity;

import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.ViewPager;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.shu.Adapter.GuideViewPagerAdapter;
import com.shu.Common.SysConfig;
import com.shu.R;


import java.util.ArrayList;
import java.util.List;

/**
 * 引导页面
 */
public class LoadingActivity extends AppCompatActivity  implements ViewPager.OnPageChangeListener, View.OnClickListener {
    private ViewPager viewpager;
    // 适配器
    private GuideViewPagerAdapter adapter;
    //View数据
    private List<View> views;
    //引导页图片、布局资源
    private int[] pics = {R.layout.guid_view1, R.layout.guid_view2, R.layout.guid_view3};
    //引导点资源
    private ImageView[] imageViews;
    //引导点
    private ImageView imageOne, imageTwo, imageThree;
    private  Button button_01;
    private  TextView textView_01;



    /**
     * 初始化
     *
     * @param savedInstanceState
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_loading);
        SharedPreferences preferences = this.getSharedPreferences( "data_init", Context.MODE_PRIVATE );
        // 未引导页过
        if(preferences.getString("flag", "").equals("")){
            viewpager = this.findViewById(R.id.viewpager);
            imageOne = this.findViewById(R.id.imageOne);
            imageTwo = this.findViewById(R.id.imageTwo);
            imageThree = this.findViewById(R.id.imageThree);
            initView();
            textView_01=findViewById(R.id.skip_home);
            textView_01.setOnClickListener(this);
        }
        else {
            GoToLogin();
        }
    }


    /**
     * 初始化布局
     */
    private void initView() {
        if (views == null) {
            views = new ArrayList<>();
        }
        if (imageViews == null) {
            imageViews = new ImageView[3];
        }
        //初始化引导点,赋值
        imageViews[0] = imageOne;
        imageViews[1] = imageTwo;
        imageViews[2] = imageThree;
        //默认全部为未选中
        setPointSelect(true, 0);
        //初始化引导页视图列表,将3个布局View添加至list中
        for (int i = 0; i < pics.length; i++) {
            View view = LayoutInflater.from(this).inflate(pics[i], null);
            views.add(view);
        }
        //初始化adapter
        adapter = new GuideViewPagerAdapter(views);
        //将adapter设置到viewpager中
        viewpager.setAdapter(adapter);
        //ViewPager切换事件
        viewpager.addOnPageChangeListener(this);
    }


    /**
     * ViewPager滑动事件
     */
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        //当前页面被滑动时调用
        //position :当前页面,及你点击滑动的页面
        //positionOffset:当前页面偏移的百分比
        //positionOffsetPixels:当前页面偏移的像素位置
    }



    /**
     * 那个页面被选择
     * @param position
     */
    @Override
    public void onPageSelected(int position) {
        //先设置为未选中,在将当前设置为选中状态
        setPointSelect(false, position);
        // 最后一个位置时
        if(position==2){
            button_01=findViewById(R.id.start_home);
            button_01.setOnClickListener(this);
        }
    }



    @Override
    public void onPageScrollStateChanged(int state) {
        //当滑动状态改变时调用
        //state ==1 的时候默示正在滑动
        //state ==2 的时候默示滑动完毕了
        //state ==0 的时候默示什么都没做
    }


    /**
     * 设置引导点为为选中状态
     */
    private void setPointSelect(boolean state, int position) {
        for (int i = 0; i < imageViews.length; i++) {
            imageViews[i].setBackgroundResource(R.drawable.unselect);
        }
        if (state) {
            //第一张为选中状态
            imageViews[0].setBackgroundResource(R.drawable.select);
        } else {
            imageViews[position].setBackgroundResource(R.drawable.select);
        }
    }


    /**
     * 点击事件
     * @param v
     */
    @Override
    public void onClick(View v) {
        // 来到登录页面
        if(v.getId() == R.id.skip_home){
            @SuppressLint("CommitPrefEdits")
            SharedPreferences.Editor editor=getSharedPreferences("data_init",MODE_PRIVATE).edit();
            editor.putString("flag","qwaszx123@A");
            editor.apply();
            GoToLogin();
        }
        // 来到登录页面
        if(v.getId()==R.id.start_home){
            @SuppressLint("CommitPrefEdits")
            SharedPreferences.Editor editor=getSharedPreferences("data_init",MODE_PRIVATE).edit();
            editor.putString("flag","qwaszx123@A");
            editor.apply();
            GoToLogin();
        }
    }


    /**
     * 跳转登录页面
     */
    public void GoToLogin(){
        Intent intent = new Intent(LoadingActivity.this, LoginActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
     overridePendingTransition(android.R.anim.fade_in,android.R.anim.fade_out);
    }
}


效果图:
image.png
到此我们的代码就编写完成了。
源码地址:https://github.com/Eason-shu/Android-Demo
喜欢或对你有用,请帮我点个star,谢谢,其余实现方式后续更新。。。。。。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-06-29 19:12:58  更:2022-06-29 19:14:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年3日历 -2024/3/29 1:58:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码