selector是什么?
selector是选择器的意思,从字面上理解应该是给我们提供可选择对象,那么在Android开发当中是什么呢?我们上一篇讲到Android样式开发中的shape,我们知道shape可以为控件设置背景,但是如果遇到这样的需求我们该怎么办呢?–对于一个button,我们点击的时候是一个图片,默认的时候是另一张图片。这样的话用shape似乎无法实现,因为shape无法控制一个控件状态的改变,对,我们要记住状态两个字,因为selector就是为多种控件在不同状态下显示不同的效果,这里的状态包括,被点击,被按压,被触摸以及被选中等状态,当一个按钮被点击和没有被点击的时候,我们可以通过selector让其显示不同的背景或者字体颜色等。
作者:root
GSONFormat的简单使用
节选自:GSONFormat的简单使用
GsonFormat 插件的用法
在Android Studio中,可以利用 GsonFormat插件,快速创建符合 Gson要求的 javaBean 。GSONFormat地址:https://github.com/zzz40500/GsonFormat
使用过程
小tip:应该直接把从接口拿到的数据粘贴,避免 api 文档格式问题带来的各种不必要的 bug
Android Studio 常用快捷键
1.全局搜索类:Ctrl + N
2.全局搜索文件:Ctrl + Shift + N
3.搜索字符串:Ctrl + F
4.全局搜索字符串:Ctrl + Shift + F
5.快速生成构造函数,Get、Set方法等:Alt + Insert
6.编辑位置回退/前进:Ctrl + Alt + 向左箭头/向右箭头
7.左右切换代码视图:Alt + 向左箭头/向右箭头
8.自动导入包:Ctrl + Alt + O
9.格式化代码:Ctrl + Alt + L
10.方法参数提示:Ctrl + P
11.用“try / catch”等包围代码:Ctrl + Alt + T
12.跳转到声明位置(PS:也可以跳转到使用位置):Ctrl + B ,Ctrl + 鼠标左键
13.跳转到实现位置:Ctrl + Alt + B
14.编辑界面横向滚动:Shift + 鼠标滚动
15.跳转到父类方法:Ctrl + U
参考链接:
数据脱敏工具类
import android.text.TextUtils; /** * 数据脱敏工具类 */ public class DataMaskingUtil { /** * 姓名脱敏 * * @param name * @return */ public static String maskName(String name) { if (TextUtils.isEmpty(name)) { return ""; } if (name.length() == 2 || name.length() == 3) { return name.replaceFirst("(.).", "$1" + "*"); } else if (name.length() == 4) { return name.substring(0, 2) + "**"; } else if (name.length() > 4) { return name.substring(0, 4) + "****"; } return name; } }
参考链接:
布局中Button始终在顶层无法被覆盖
最近写项目时遇到一个很奇怪的问题,在Relativelayout中Button始终在最顶层,无法被其他控件覆盖,然后试了下在Android 5.0以下的版本可以被正常覆盖,几经周折,终于找到了原因。
产生原因:stateListAnimator属性
谷歌在Material Design中推出,是一个非常简单的方法用来实现在可视状态之间平滑过渡。这个属性可以通过android:stateListAnimator进行设置,可以使控件在点击时产生不同的交互。对于Button,点击时默认有个阴影的效果用于表示按下的状态(5.0以前就是简单的变色)。
解决方法:
1.如果Button已经有自定义的selector样式而不需要原生的按下后的阴影效果,可以使用android:stateListAnimator=”@null”去掉阴影效果而使Button可以被正常的覆盖
2.如果希望保留Button的阴影效果而又想使其能够被覆盖,则应该使用个单独的Linearlayout对Button进行包裹,记住要给Button的下方和左右侧留出空余。这种方法虽然不符合规范,但是为了需求只得这么做了。
代码示例:
<LinearLayout android:layout_width="match_parent" android:layout_height="52dp"> <Button android:id="@+id/btn" android:layout_width="match_parent" android:layout_height="42dp" android:layout_marginLeft="30dp" android:layout_marginRight="30dp" android:background="@drawable/login_btn_selector" android:text="@string/app_login" tools:ignore="UselessParent" android:textColor="@color/white" android:textSize="20sp" /> </LinearLayout>
切换Fragment
private Fragment nowFragment; /** * 切换Fragment * * @param fragment */ private void switchFragment(Fragment fragment) { FragmentTransaction transaction = fragmentManager.beginTransaction(); if (nowFragment != null) { transaction.hide(nowFragment); } transaction.show(fragment).commit(); nowFragment = fragment; }
参考链接:
Android开发命名规范和编码规范
命名规范要望文知义,简单明了。
命名规范定制太多,就会让人心烦,反而没人遵守了。
—《APP研发录》
先介绍两种命名规则:
- 驼峰命名法:又称小驼峰命名法。除了首个单词首字母小写除外,其余所有单词所有首字母都要大写。
- 帕斯卡命名法:又称大驼峰命名法。所有单词首字母大写。
自定义View之组合View
import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageButton; import android.widget.ImageView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.bumptech.glide.Glide; import cn.xiaocaimei.devicemanager.R; import cn.xiaocaimei.devicemanager.base.BasePanel; public class ShowImagePanel extends FrameLayout { // 界面 private ImageView imgFace; public ShowImagePanel(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); initView(context); } @Override protected void initView(Context context) { LayoutInflater.from(context).inflate(R.layout.panel_show_image, this, true); // 返回按钮 ImageButton closeBtn = findViewById(R.id.closeBtn); closeBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { setVisibility(GONE); } }); // 背景返回 setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { setVisibility(GONE); } }); // 头像图片 imgFace = findViewById(R.id.imgFace); } /** * 展示图片 * * @param url */ public void showImage(String url) { Glide.with(this).load(url).into(imgFace); setVisibility(VISIBLE); } }
参考链接:
Object.requireNonNull 方法说明
节选自:Object.requireNonNull 方法说明
首先, 从这个方法的名称可以看出, 这个方法使用的场景是, 我们使用一个对象的方法时, 正常的运行状态应该能保证这个对象的引用非空, 如果这个对象为空了, 那一定是其他某个地方出错了, 所以我们应该抛出一个异常, 我们不应该在这里处理这个非空异常.
其次, 这里涉及到一个很重要的编程思想, 就是 Fail-fast 思想, 翻译过来就是, 让错误尽可能早的出现, 不要等到我们很多工作执行到一半之后才抛出异常, 这样很可能使得一部分变量处于异常状态, 出现更多的错误. 这也是 requireNonNull 这个方法的设计思想, 让错误尽早出现. 使用这个方法, 我们明确的抛出异常, 发生错误时, 我们立刻抛出异常.
5分钟搞定PopUpWindow
节选自:5分钟搞定PopUpWindow
弹窗有很多种实现方式,例如:
- Dialog
- DialogFragment
- Fragment
- PopUpWindow
- ListPopUpWindow
在这些方式中,我们主要讲 PopUpWindow 的使用方式,因为它能在任意位置弹出, 这是其他方式很难做到的。
PopUpWindow 是什么
从 Google 爸爸的开发文档中我们不难看出,首先它是一个 Window,弹出时位于其他控件的上层。
怎么使用 PopUpWindow
- 创建布局文件
- 创建 ContentView
- 设置 PopUpWindow
- Show