Android学习之旅1D:首屏页的开发

文章目录
  1. Android学习之旅:第一天
    1. I. 前置
    2. II. Splash页面开发
      1. 1. 做什么
      2. 2. 开动
        1. a. 全屏
        2. b. xml实现
        3. c. Activity的实现
        4. todo
    3. III. 知识点小结
      1. 1. RelativeLayout 布局
      2. 2. 获取组件
      3. 3. 设置动画
      4. 4. 页面跳转
    4. IV. 倒计时改进
    5. V. 其他
      1. 额外话
      2. 扫描关注,java分享

Android学习之旅:第一天

采用依葫芦画瓢的方式来学习android的开发,准备逐步的开发出《一封》这个app

本片主要记录了SplashActivity的开发过程

I. 前置

主要copy两个开源项目

  1. JianshuApp
  2. SUESNews

上面两个工程,第二个用到的依赖比较少,实现的基本功能也都很ok,而第一个里面则用了很多有意思的第三方框架,但是目前我看不太懂,所以第一版以SUESNews作为主要的学习目标

所以,第一版的目标是:

  • 实现基本功能
  • 完成主体业务逻辑

II. Splash页面开发

一般来将,进入app之前,会进入一个类似首屏页的页面(比如12306的显示广告啥的),那么第一件事情就是做这个了

1. 做什么

这个页面,主要显示的东西比较简单了

  • 上边是一个图片,右上角一个倒计时
  • 下边显示的应用信息,版本等

业务逻辑:

  • 显示广告(😄),点击进入相应的详情页
  • 判断是否登录,若未登录,则进入登录页
  • 若已经登录,则进入主APP

2. 开动

a. 全屏

进入的首页,所以状态栏,标题啥的都不要,主要的逻辑如下

styles.xml 文件中新增

1
2
3
4
<style name="AppTheme.FullScreen">
<item name="windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
</style>

其次,就是在定义的Activity中,使用对应的style

AndroidManifest.xml

1
2
3
4
5
6
7
<activity android:name=".ui.SplashActivity"
android:theme="@style/AppTheme.FullScreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

b. xml实现

activity_splash.xml 对应的实现如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?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:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="false"
tools:context="com.yihui.yifeng.ui.SplashActivity">

<ImageView
android:id="@+id/image_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignBottom="@+id/title_text"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginBottom="52dp"
android:scaleType="centerCrop" />


<ImageView
android:id="@+id/image_info_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignTop="@+id/title_text"
android:layout_centerHorizontal="true"
android:scaleType="centerCrop" />

<TextView
android:id="@+id/title_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/version_text"
android:layout_centerHorizontal="true"
android:layout_marginBottom="17dp"
android:text="@string/app_name"
android:textColor="@color/text_color"
android:textSize="@dimen/text_size_title_bigger"
android:textStyle="bold" />

<TextView
android:id="@+id/version_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="11dp"
android:textColor="@color/secondary_text"
android:textSize="@dimen/text_size_subhead"
android:textStyle="bold"
tools:text="Copyright @2017-2018 一封 | 小灰灰技术支持" />

</RelativeLayout>

运行截图如下:

A7108014-E6AC-4327-91F2-A89F07EEFE53.png

上面这个布局,是直接使用可视化的拖拽的,所以操作起来挺蛋疼的,而且最终的结果也不太好,下面单独的开一节来研究下这个布局的东西了

c. Activity的实现

上面是xml的配置,当然还得有对应的实体类了,大部分逻辑是直接从参考的工程中copy过来的,所以相关的动画配置,图片也是直接扣过来的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public class SplashActivity extends Activity {

private ImageView mBackgroundImage;

private ImageView infoBgImg;

private TextView mTitleText;

private TextView mVersionText;

private int[] ary = new int[] {R.drawable.pic_background_1, R.drawable.pic_background_2, R.drawable.pic_background_3, R.drawable.pic_background_4};

private int getBgDrawable() {
return ary[new Random().nextInt(ary.length)];
}


private void initInfoBg() {
infoBgImg = findViewById(R.id.image_info_bg);
infoBgImg.setImageDrawable(getResources().getDrawable(ary[0]));
}


private void initAdBg() {
mBackgroundImage = findViewById(R.id.image_background);
mBackgroundImage.setImageDrawable(getResources().getDrawable(getBgDrawable()));

Animation animImage = AnimationUtils.loadAnimation(this, R.anim.image_welcome);
mBackgroundImage.startAnimation(animImage);
animImage.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}

@Override
public void onAnimationEnd(Animation animation) {
//动画结束时打开首页
startActivity(new Intent(SplashActivity.this, MainActivity.class));
overridePendingTransition(R.anim.activity_slide_in, R.anim.no_anim);
finish();
}

@Override
public void onAnimationRepeat(Animation animation) {

}
});
}


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);

// 下半的提示文案信息
initInfoBg();


// 上半的广告动画
initAdBg();
}
}

todo

登录状态判断,如果未登录,则应该跳转到登录页面;否则才是跳转到主页

III. 知识点小结

上面只是实现了一个简单的应用开启页面,但也涉及了几个有趣的知识点,下面来深入一下

1. RelativeLayout 布局

控件的位置是按照相对位置来计算的,后一个控件在什么位置依赖于前一个控件的基本位置,是布局最常用,也是最灵活的一种布局

常见的属性值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
第一类:属性值为true或false
android:layout_centerHrizontal 水平居中
android:layout_centerVertical 垂直居中
android:layout_centerInparent 相对于父元素完全居中
android:layout_alignParentBottom 贴紧父元素的下边缘
android:layout_alignParentLeft 贴紧父元素的左边缘
android:layout_alignParentRight 贴紧父元素的右边缘
android:layout_alignParentTop 贴紧父元素的上边缘  

第二类:属性值必须为id的引用名“@id/id-name”
android:layout_below 在某元素的下方
android:layout_above 在某元素的的上方
android:layout_toLeftOf 在某元素的左边
android:layout_toRightOf 在某元素的右边
android:layout_alignTop 本元素的上边缘和某元素的的上边缘对齐
android:layout_alignLeft 本元素的左边缘和某元素的的左边缘对齐
android:layout_alignBottom 本元素的下边缘和某元素的的下边缘对齐
android:layout_alignRight 本元素的右边缘和某元素的的右边缘对齐

第三类:属性值为具体的像素值,如30dip,40px
android:layout_marginBottom 离某元素底边缘的距离
android:layout_marginLeft 离某元素左边缘的距离
android:layout_marginRight 离某元素右边缘的距离
android:layout_marginTop 离某元素上边缘的距离

所以可以简单的修改一下上面的布局,相对布局的样式就两个,上面一个图,下面一个图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<ImageView
android:id="@+id/image_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
<!-- 注意这一行 -->
android:layout_alignBottom="@+id/image_info_bg"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginBottom="52dp"
android:scaleType="centerCrop" />


<ImageView
android:id="@+id/image_info_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
<!-- 注意这一行,确保背景图可以包含文本信息 -->
android:layout_alignTop="@+id/title_text"
android:layout_centerHorizontal="true"
android:scaleType="centerCrop" />

那么剩下的两个文本显示就可以直接指定下边距来确定位置了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<TextView
android:id="@+id/title_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/version_text"
android:layout_centerHorizontal="true"
<!-- 这里确定了高度 -->
android:layout_marginBottom="17dp"
android:text="@string/app_name"
android:textColor="@color/text_color"
android:textSize="@dimen/text_size_title_bigger"
android:textStyle="bold" />

<TextView
android:id="@+id/version_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
<!-- 这里确定了高度 -->
android:layout_marginBottom="11dp"
android:textColor="@color/secondary_text"
android:textSize="@dimen/text_size_subhead"
android:text="@string/splash_copyright" />

2. 获取组件

在Activity中,先要绑定视图,然后再获取view进行相关的操作(如修改值,绑定事件等)

1
2
3
4
5
6
7
8
9
10
// Activity 的 oncreate方法中,进行初始化
// 绑定视图
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);

// 获取组件
findViewById(R.id.image_info_bg);

// 获取资源,如图片
Drawable drawable = getResources().getDrawable(R.drawable.pic_background_1)

有一个非常有名的工具叫做 butterknife, 可以通过注解的方式来解决 findViewById这种频繁的调用姿势,这个放在后续的进阶版中使用

3. 设置动画

开屏使用了一个图片放大的动画,持续3s,动画播放完毕之后跳转主页;所以这里有个有趣的知识点就是如何使用xml来配置动画效果,从实现来看也挺简单的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 解析xml配置为 Animation 对象
Animation animImage = AnimationUtils.loadAnimation(this, R.anim.image_welcome);
// 设置组件的动画属性
mBackgroundImage.startAnimation(animImage);
// 配置监听事件
animImage.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}

// 动画结束后的回调
@Override
public void onAnimationEnd(Animation animation) {
//动画结束时打开首页
startActivity(new Intent(SplashActivity.this, MainActivity.class));
overridePendingTransition(R.anim.activity_slide_in, R.anim.no_anim);
finish();
}

@Override
public void onAnimationRepeat(Animation animation) {

}
});

对应的xml配置如下

image_welcome.xml

1
2
3
4
5
6
7
8
9
10
11
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:fromXScale="1.0"
android:toXScale="1.3"
android:fromYScale="1.0"
android:toYScale="1.3"
android:duration="3000"
android:pivotY="50%"
android:pivotX="50%"
/>
</set>

那么,我们需要实现开头说的,这个图片如果是个广告,点击时展开详情页;右上角显示一个倒计时的小控件,可以怎么处理?(看最后)

4. 页面跳转

从一个Activity跳转到另一个,常见的使用姿势如下

1
startActivity(new Intent(SplashActivity.this, MainActivity.class));

IV. 倒计时改进

如何使用倒计时来替换前面的动画呢?最容易想到的就是用Timer或者ScheduleService来实现一个计时器,当然这是一个后端java的想法,对于Android呢,特意查了一下,发现有个 CountDownTimer 的类,专门干这个的,所以简单的改造一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private void initAdBg() {
mBackgroundImage = findViewById(R.id.image_background);
mBackgroundImage.setImageDrawable(getResources().getDrawable(getBgDrawable()));
mBackgroundImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 点击
Toast.makeText(SplashActivity.this, "点击了", Toast.LENGTH_SHORT).show();
}
});

final TextView countDown = findViewById(R.id.splash_timedown);
CountDownTimer timer = new CountDownTimer(10000, 1000) {
@Override
public void onTick(long l) {
countDown.setText("倒计时:" + (l / 1000) + "s");
}

@Override
public void onFinish() {
//动画结束时打开首页
startActivity(new Intent(SplashActivity.this, MainActivity.class));
overridePendingTransition(R.anim.activity_slide_in, R.anim.no_anim);
finish();
}
};
timer.start();
}

改造后的输出图, 注意右上角的时间,已经下面分割处,不会有前面的空白了

7694230F-D9FE-4DCE-B76B-75E3204D3571.png

V. 其他

额外话

感觉最近不太能专心下来学习一门技术,有点浮躁了,所以决定学习下andorid,锻炼下自己,初步规划,先入门,然后接收一些有趣的第三方框架,最后再试一下kotalin

Android学习第一天,总感觉这将是个漫长的过程,也不晓得最终会完成得怎么样,努力坚持吧

扫描关注,java分享

QrCode

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×