android实现App第一次进入时的引导学习界面
时间:2022-06-26
本文章向大家介绍android实现App第一次进入时的引导学习界面
,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
因为我们所熟知的Android平台是一个又一个的Activity组成的,每一个Activity有一个或者多个View构成。所以说,当我们想显示一个界面的时候,我们首先想到的是建立一个Activity,然后所有的操作在Activity里面实现,或者是一个Dialog或者Toast。这种方式固然简单,但是在有些情况下,我们要求的只是简单的显示,用Activity显然是多余,这个时候,我们如何处理呢?
原来,整个Android的窗口机制是基于一个叫做 WindowManager,这个接口可以添加view到屏幕,也可以从屏幕删除view。
其实我们的Activity或者Diolog底层的实现也是通过WindowManager,这个 WindowManager是全局的,在整个系统是唯一的。它是显示View的最底层了。
效果图:
点击屏幕任何一个位置,引导界面消失
源码分析
- 两个类:GuideUtil,ScreenUtils
- 两个动画文件:fade_in.xml ,fade_out.xml
- 一个在主activity:MainActivity
先看看MainActivity 中如何使用这两个类,再深入其中看看这两个类怎么工作
1、MainActivity
public class MainActivity extends Activity {
private GuideUtil guideUtil = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**获取引导界面工具类的实例**/
guideUtil = GuideUtil.getInstance();
/**显示引导界面,程序一启动就会显示引导界面**/
guideUtil.initGuide(this, R.drawable.add_guide);
findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
/**如果引导界面消失了,可点击这个按钮,显示引导界面**/
guideUtil.initGuide(MainActivity.this, R.drawable.add_guide);
}
});
findViewById(R.id.button2).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
/**实际程序中,如果不是第一次,那不会显示引导界面。
在setFirst中设置false,模拟这个效果。
点击上面的按钮,不会再弹出引导界面**/
//是否是第一次进入app
guideUtil.setFirst(false);
guideUtil.initGuide(MainActivity.this, R.drawable.add_guide);
}
});
}
}
2、GuideUtil
初始化引导图层,并设置一个事件。
/**
* @类名:GuideUtil
* @类描述:引导工具界面
* @修改人:
* @修改时间:
* @修改备注:
* @版本:
*/
public class GuideUtil {
private Context context;
private ImageView imgView;
private WindowManager windowManager;
private static GuideUtil instance = null;
/** 是否第一次进入该程序 **/
private boolean isFirst = true;
/**采用私有的方式,只保证这种通过单例来引用,同时保证这个对象不会存在多个**/
private GuideUtil() {
}
/**采用单例的设计模式,同时用了同步锁**/
public static GuideUtil getInstance() {
synchronized (GuideUtil.class) {
if (null == instance) {
instance = new GuideUtil();
}
}
return instance;
}
private Handler handler = new Handler(Looper.getMainLooper()) {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case 1:
// 设置LayoutParams参数
final LayoutParams params = new WindowManager.LayoutParams();
// 设置显示的类型,TYPE_PHONE指的是来电话的时候会被覆盖,其他时候会在最前端,显示位置在stateBar下面,其他更多的值请查阅文档
params.type = WindowManager.LayoutParams.TYPE_PHONE;
// 设置显示格式
params.format = PixelFormat.RGBA_8888;
// 设置对齐方式
params.gravity = Gravity.LEFT | Gravity.TOP;
// 设置宽高
params.width = ScreenUtils.getScreenWidth(context);
params.height = ScreenUtils.getScreenHeight(context);
// 设置动画
params.windowAnimations = R.style.view_anim;
// 添加到当前的窗口上
windowManager.addView(imgView, params);
break;
}
};
};
/**
* @方法说明:初始化
* @方法名称:initGuide
* @param context
* @param drawableRourcesId:引导图片的资源Id
* @返回值:void
*/
public void initGuide(Activity context, int drawableRourcesId) {
/**如果不是第一次进入该界面**/
if (!isFirst) {
return;
}
this.context = context;
windowManager = context.getWindowManager();
/** 动态初始化图层**/
imgView = new ImageView(context);
imgView.setLayoutParams(new LayoutParams(
android.view.ViewGroup.LayoutParams.MATCH_PARENT,
android.view.ViewGroup.LayoutParams.MATCH_PARENT));
imgView.setScaleType(ScaleType.FIT_XY);
imgView.setImageResource(drawableRourcesId);
/**这里我特意用了一个handler延迟显示界面,主要是为了进入界面后,你能看到它淡入得动画效果,不然的话,引导界面就直接显示出来**/
handler.sendEmptyMessageDelayed(1, 1000);
imgView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
/** 点击图层之后,将图层移除**/
windowManager.removeView(imgView);
}
});
}
public boolean isFirst() {
return isFirst;
}
/**
* @方法说明:设置是否第一次进入该程序
* @方法名称:setFirst
* @param isFirst
* @返回值:void
*/
public void setFirst(boolean isFirst) {
this.isFirst = isFirst;
}
}
3、ScreenUtils
这个类主要获取屏幕的宽度和高度
ScreenUtils类,在只有44 和45 两个地方有用到
/**
* @类名:ScreenUtils
* @类描述:屏幕工具类
* @修改人:
* @修改时间:
* @修改备注:
* @版本:
*/
public class ScreenUtils {
/**
* @方法说明:获取DisplayMetrics对象
* @方法名称:getDisPlayMetrics
* @param context
* @return
* @返回值:DisplayMetrics
*/
public static DisplayMetrics getDisPlayMetrics(Context context) {
DisplayMetrics metric = new DisplayMetrics();
if (null != context) {
((Activity) context).getWindowManager().getDefaultDisplay()
.getMetrics(metric);
}
return metric;
}
/**
* @方法说明:获取屏幕的宽度(像素)
* @方法名称:getScreenWidth
* @param context
* @return
* @返回值:int
*/
public static int getScreenWidth(Context context) {
int width = getDisPlayMetrics(context).widthPixels;
return width;
}
/**
* @方法说明:获取屏幕的高(像素)
* @方法名称:getScreenHeight
* @param context
* @return
* @返回值:int
*/
public static int getScreenHeight(Context context) {
int height = getDisPlayMetrics(context).heightPixels;
return height;
}
/**
* @方法说明:屏幕密度(0.75 / 1.0 / 1.5)
* @方法名称:getDensity
* @param context
* @return
* @返回 float
*/
public static float getDensity(Context context) {
float density = getDisPlayMetrics(context).density;
return density;
}
/**
* @方法说明:屏幕密度DPI(120 / 160 / 240)
* @方法名称:getDensityDpi
* @param context
* @return
* @返回 int
*/
public static int getDensityDpi(Context context) {
int densityDpi = getDisPlayMetrics(context).densityDpi;
return densityDpi;
}
}
4、两个动画文件
fade_in.xml
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
fade_out.xml
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
源码下载:
原作者想赚点资源分,提供了eclipse项目代码,如果手头分数还算宽裕,去原作者那里下载吧
如果没有分的并且不会转化为AS项目的,我提供了这个下载地址。
- oracle工具集初探(r4笔记第8天)
- Spring+SpringMVC+MyBatis+easyUI整合优化篇(二)Log4j讲解与整合
- 京东JData算法大赛-高潜用户购买意向预测(github源码)
- 巧用linux命令做图片下载器(r4笔记第7天)
- Spring+SpringMVC+MyBatis+easyUI整合优化篇(四)单元测试实例
- Spring+SpringMVC+MyBatis+easyUI整合优化篇(五)结合MockMvc进行服务端的单元测试
- 关于order by中的数据排序(r4笔记第6天)
- 深度学习CTPN+CRNN模型实现图片内文字的定位与识别(OCR)
- Markdown语法讲解及MWeb使用教程
- 通过Linu命令实现屏幕录制和回放(r4笔记第5天)
- 用keras对国产剧评论文本的情感进行预测
- python常用可视化技巧
- Spring+SpringMVC+MyBatis+easyUI整合基础篇(六)maven整合SSM
- 通过java程序抽取日志中的sql语句(r4笔记第4天)
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Qt音视频开发25-ffmpeg音量设置
- 从HelloWorld开始了解Android
- 探究活动Activity
- 探究活动Activity(2)界面跳转及生命周期
- Android-MediaPlayer
- 如何友好的把Python和Bash结合在一起
- Android-MediaPlayer(2)加进度条和时间显示
- Android-MediaPlayer(3)加打碟旋转效果
- 解决This Gradle plugin requires a newer IDE able to request IDE model level 3. For Android Studio
- 你不就是加了 2 行代码,为什么要用 2 天?
- Android 使用ZXing生成带logo的二维码
- Resolved versions for app (26.1.0) and test app (27.1.1) differ.
- APP 引导页、欢迎页运用
- 管道与重定向、文件查找-Linux每日一练(7)
- 软件包管理、计划任务-Linux每日一练(8)