Android学习之旅:第一天
采用依葫芦画瓢的方式来学习android的开发,准备逐步的开发出《一封》这个app
本片主要记录了SplashActivity的开发过程
I. 前置
主要copy两个开源项目
- JianshuApp
- SUESNews
上面两个工程,第二个用到的依赖比较少,实现的基本功能也都很ok,而第一个里面则用了很多有意思的第三方框架,但是目前我看不太懂,所以第一版以SUESNews作为主要的学习目标
所以,第一版的目标是:
II. Splash页面开发
一般来将,进入app之前,会进入一个类似首屏页的页面(比如12306的显示广告啥的),那么第一件事情就是做这个了
1. 做什么
这个页面,主要显示的东西比较简单了
- 上边是一个图片,右上角一个倒计时
- 下边显示的应用信息,版本等
业务逻辑:
- 显示广告(😄),点击进入相应的详情页
- 判断是否登录,若未登录,则进入登录页
- 若已经登录,则进入主APP
2. 开动
a. 全屏
进入的首页,所以状态栏,标题啥的都不要,主要的逻辑如下
styles.xml 文件中新增
| 12
 3
 4
 
 | <style name="AppTheme.FullScreen"><item name="windowNoTitle">true</item>
 <item name="android:windowFullscreen">true</item>
 </style>
 
 | 
其次,就是在定义的Activity中,使用对应的style
AndroidManifest.xml
| 12
 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 对应的实现如下
| 12
 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>
 
 | 
运行截图如下:

上面这个布局,是直接使用可视化的拖拽的,所以操作起来挺蛋疼的,而且最终的结果也不太好,下面单独的开一节来研究下这个布局的东西了
c. Activity的实现
上面是xml的配置,当然还得有对应的实体类了,大部分逻辑是直接从参考的工程中copy过来的,所以相关的动画配置,图片也是直接扣过来的
| 12
 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 布局
控件的位置是按照相对位置来计算的,后一个控件在什么位置依赖于前一个控件的基本位置,是布局最常用,也是最灵活的一种布局
常见的属性值
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | 第一类:属性值为true或falseandroid: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 离某元素上边缘的距离
 
 | 
所以可以简单的修改一下上面的布局,相对布局的样式就两个,上面一个图,下面一个图
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | <ImageViewandroid: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" />
 
 | 
那么剩下的两个文本显示就可以直接指定下边距来确定位置了
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | <TextViewandroid: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进行相关的操作(如修改值,绑定事件等)
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | 
 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来配置动画效果,从实现来看也挺简单的
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | 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
| 12
 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 的类,专门干这个的,所以简单的改造一下
| 12
 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();
 }
 
 | 
改造后的输出图, 注意右上角的时间,已经下面分割处,不会有前面的空白了

V. 其他
额外话
感觉最近不太能专心下来学习一门技术,有点浮躁了,所以决定学习下andorid,锻炼下自己,初步规划,先入门,然后接收一些有趣的第三方框架,最后再试一下kotalin
Android学习第一天,总感觉这将是个漫长的过程,也不晓得最终会完成得怎么样,努力坚持吧
扫描关注,java分享
