A Blog to Write about Everything

0%

收到多次需要夜间模式的反馈,就研究了一下要怎么实现~

本以为需要手动替换Theme,实际上Android已经提供了相应的功能。

实际使用之后才发现,Fragment能实现到和Activity在使用上分辨不出的效果。

依赖

首先是依赖,需要使用appcompat:(我这里用的androidx库,support库同理)

1
implementation 'androidx.appcompat:appcompat:1.1.0-beta01'
阅读全文 »

参考: https://www.jianshu.com/p/93bb4d049955

最近的一条记录

如果只是需要修改最近的一条记录的话,只需要

1
git commit --amend --author="作者名 <邮箱@xxxx.com>"

注意:这里的尖括号是要带上的。

多条记录

1
2
3
4
5
6
7
8
9
10
# 第一步,(n)代表提交次数
git rebase -i HEAD~n
# 第二步
然后按`i`编辑,把`pick` 改成 `edit`,按'Esc'退出编辑,按`:wq`保存退出
# 第三步
git commit --amend --author="作者 <邮箱@xxxx.com>" --no-edit
# 第四步(多条记录的话,会跳转到下一条记录,返回第三步)
git rebase --continue
# 第五步(全部完成后,覆盖远程git记录,危险操作要谨慎操作)
git push --force

非常多条记录更改

转自网络:

如果是多个修改,那么就需要使用到git filter-branch这个工具来做批量修改
为了方便大家使用,封装了一个简单的shell脚本,直接修改[XXX]中的变量为对应的值即可

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
#!/bin/sh

git filter-branch --env-filter '

an="$GIT_AUTHOR_NAME"
am="$GIT_AUTHOR_EMAIL"
cn="$GIT_COMMITTER_NAME"
cm="$GIT_COMMITTER_EMAIL"

if [ "$GIT_COMMITTER_EMAIL" = "[Your Old Email]" ]
then
cn="[Your New Author Name]"
cm="[Your New Email]"
fi
if [ "$GIT_AUTHOR_EMAIL" = "[Your Old Email]" ]
then
an="[Your New Author Name]"
am="[Your New Email]"
fi

export GIT_AUTHOR_NAME="$an"
export GIT_AUTHOR_EMAIL="$am"
export GIT_COMMITTER_NAME="$cn"
export GIT_COMMITTER_EMAIL="$cm"
'

以此文总结一下《LifeUp》上架 GooglePlay 的全过程~

多语言

App默认会根据系统语言加载不同的字符串资源文件,这是我们实现多语言的基础。

新建资源文件

首先是建立相应的资源文件,可以手动建立,也可以用 Android Studio 的选项建立:

右键 res 文件夹选择File–>New–>Android resource file选择 Locale

可以见到下图

选择你要新建的语言,并且改文件名为strings即可。

实际上,就是新建一个value-(语言缩写)的文件夹(简体中文的话就是value-zh),然后在其中放上string.xml文件。

提取代码、Layout中的字符串

点击相应的字符串,按下ALT+ENTER,然后选择 Extract string resouces

然后输入字符串资源的名称,勾选相应的资源文件:

按下确定后,AS就会提取该字符串到资源文件内了,同时代码会被替换成:

Context getString(resouceId)

在Layout中操作同理,利用这个操作可以替换掉App内大部分的静态的字符串。

那么需要动态赋值的字符串该怎么办呢?

阅读全文 »

Toolbar 默认配置下,标题和Navigation icon(比如返回按钮)之间的间隔会迷之过长,

可以通过配置toolbar的属性调整:

1
app:contentInsetStartWithNavigation="0dp"

这个间隔的设计好像是配合没有Navigation icon的情况的,默认值为16dp。

有Navigation icon的情况下应该手动调整。

完整的Toolbar配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">

<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:contentInsetStartWithNavigation="0dp"
app:popupTheme="@style/AppTheme.PopupOverlay" />

</com.google.android.material.appbar.AppBarLayout>

简介

之前在《人升》的桌面小部件,实现ListView中的点击事件监听的方式是:

使用fillInIntent发送广播到Widget类中,并在onReceive方法中拦截,处理业务逻辑。

但是,

Widget的本质是个广播接收器,不适宜在里面处理耗时操作。

(完成团队事项的时候需要发送网络请求,普通事项需要更改数据库,都可以视为是耗时操作。)

所以,我决定改用IntentService处理完成事项的业务逻辑。

IntentService的特点是后台运行、自动销毁、异步运行。

首先尝试直接用fillInIntent启动服务失败了。

然后改成了先发送广播,然后在Widget类中,并在onReceive方法拦截再启动IntentService:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)

if (...) {
...
} else if (intent.action == FINISH_TASK) {
// 将耗时操作交给IntentService完成
val finishIntent = Intent(context, FinishTaskIntentService::class.java)
if (intent.extras != null) {
finishIntent.putExtras(intent.extras!!)
}

try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(finishIntent)
} else {
context.startService(finishIntent)
}
} catch (e: Exception) {
e.printStackTrace()
ToastUtils.showShortToast("完成事项似乎出现了一些问题,请尝试刷新下。", LifeUpApplication.getLifeUpApplication())
}
}
}

然后就遇到了坑。

阅读全文 »

简介

Snackbar 是一个底部弹出消息的控件,类似Toast。

基本使用:

1
2
3
Snackbar.make(view, message_text, duration)
.setAction(action_text, click_listener)
.show();

我们知道,在根布局是CoordinatorLayout,并且设置CoordinatorLayout的behavior之后,可以实现Snackbar弹出的时候,fab(浮动按钮)会自动向上移动防止被遮挡。

阅读全文 »

之前使用Fragment都是配合ViewPager或者配合TabLayout+ViewPager,基本没用过FragmentManager。

实际使用之后才发现,Fragment能实现到和Activity在使用上分辨不出的效果。

布局文件

其实我们要实现的效果很简单,一个主Fragment显示各个设置的大类(比如显示设置、小部件设置等),点击之后切换到不同的Fragment显示,然后那些Fragment只能回退到主Fragment,主Fragment再回退就是结束Activity。

大概这样:

Fragment的布局文件正常就好。

Activity要怎么样呢?我们的Activity本身是不需要任何内容的,只需要充当一个容器的作用就行:

activity_setting.xml

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/background_color"
android:fitsSystemWindows="true"
tools:context=".activities.SettingActivity">

</LinearLayout>
阅读全文 »

ViewPager + Fragments 导致的选项菜单错乱解决

原先的Toolbar实现

在Fragment中获取Toolbar这个View,然后调用Activity的setSupportActionBar(toolbar)方法。

然后实现Option菜单的方法:在Fragment中设置setHasOptionsMenu(true),然后重写fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater)方法。

出现的问题:似乎是因为ViewPager的缓存机制,导致切换Fragments切换的时候可能出现菜单错乱的情况。

解决:把Toolbar当做控件使用

MainActivity.kt

1
2
3
4
5
6
7
8
9
10
11
12
13
fun initToolBar(toolbar: Toolbar) {
//setSupportActionBar(toolbar) 注释掉这条

currentToolbar = toolbar
val toggle = ActionBarDrawerToggle(
this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
drawer_layout.addDrawerListener(toggle)
nav_view.setNavigationItemSelectedListener(this)
}

fun getCurrentToolbar(): Toolbar? {
return currentToolbar
}

Fragment.kt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private fun initToolbar(view: View) {
//设置toolbar
mToolbar = view.findViewById(R.id.toolbar)
(activity as MainActivity).initToolBar(mToolbar)

// 填充菜单
mToolbar?.inflateMenu(R.menu.main)
mToolbar?.setOnMenuItemClickListener { item ->
when (item.itemId) {
R.id.action_sort -> {
// do something
true
}
else -> true
}
}
}
阅读全文 »

AndroidX是 Google 发布的对原来的支持库整理后的新一代支持库。并且原来的支持库的最后版本将停留在“28.0.0”,迁移是迟早的事情。

主要动机还是想要用一个框架,结果它只支持AndroidX,就这样决定开始迁移了。

利用Android Studio迁移

需求:Android Studio版本3.2以上

操作:Refactor -> Migrate to Androidx

IDE会询问是否要备份一份当前的项目,并且会告知可能需要你手动解决一些项目Error。

继续操作,IDE会搜索所有的要改变的依赖路径,然后点击DO REFACTOR按钮吧。

阅读全文 »