Android学习之旅:第一天
采用依葫芦画瓢的方式来学习android的开发,准备逐步的开发出《一封》这个app
本片主要记录了SplashActivity的开发过程
I. 前置
主要copy两个开源项目
- JianshuApp
- 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>
|
运行截图如下:
上面这个布局,是直接使用可视化的拖拽的,所以操作起来挺蛋疼的,而且最终的结果也不太好,下面单独的开一节来研究下这个布局的东西了
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
|
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
| 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(); }
|
改造后的输出图, 注意右上角的时间,已经下面分割处,不会有前面的空白了
V. 其他
额外话
感觉最近不太能专心下来学习一门技术,有点浮躁了,所以决定学习下andorid,锻炼下自己,初步规划,先入门,然后接收一些有趣的第三方框架,最后再试一下kotalin
Android学习第一天,总感觉这将是个漫长的过程,也不晓得最终会完成得怎么样,努力坚持吧
扫描关注,java分享