布局中Button始终在顶层无法被覆盖

节选自:布局中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>

Android开发命名规范和编码规范

节选自: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) {
        super(context);
        initView(context);
    }

    public ShowImagePanel(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }

    public ShowImagePanel(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        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);
    }
}

参考链接:

自定义View之组合View

Object.requireNonNull 方法说明

节选自:Object.requireNonNull 方法说明


首先, 从这个方法的名称可以看出, 这个方法使用的场景是, 我们使用一个对象的方法时, 正常的运行状态应该能保证这个对象的引用非空, 如果这个对象为空了, 那一定是其他某个地方出错了, 所以我们应该抛出一个异常, 我们不应该在这里处理这个非空异常.

其次, 这里涉及到一个很重要的编程思想, 就是 Fail-fast 思想, 翻译过来就是, 让错误尽可能早的出现, 不要等到我们很多工作执行到一半之后才抛出异常, 这样很可能使得一部分变量处于异常状态, 出现更多的错误. 这也是 requireNonNull 这个方法的设计思想, 让错误尽早出现. 使用这个方法, 我们明确的抛出异常, 发生错误时, 我们立刻抛出异常.

5分钟搞定PopUpWindow

节选自:5分钟搞定PopUpWindow


弹窗有很多种实现方式,例如:

  1. Dialog
  2. DialogFragment
  3. Fragment
  4. PopUpWindow
  5. ListPopUpWindow

在这些方式中,我们主要讲 PopUpWindow 的使用方式,因为它能在任意位置弹出, 这是其他方式很难做到的。

PopUpWindow 是什么

从 Google 爸爸的开发文档中我们不难看出,首先它是一个 Window,弹出时位于其他控件的上层。

怎么使用 PopUpWindow

  • 创建布局文件
  • 创建 ContentView
  • 设置 PopUpWindow
  • Show

Android软键盘显示隐藏事件监听

节选自:Android软键盘显示隐藏事件监听


由于安卓系统并没有提供软键盘弹入和弹出的系统方法,所以我们有时候需要用到监听软件盘的时候会非常的麻烦,今天我根据监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变超过一定的数值来监听软键盘的弹入弹出事件,使用起来也非常简单.

继续阅读Android软键盘显示隐藏事件监听

使用单Activity多Fragment架构的一些总结

节选自:使用单Activity多Fragment架构的一些总结


MainFragment中,PagerAdapter的FragmentManager要使用Fragment的FragmentManager,通过getChildFragmentManager()获得,而不能使用getActivity().getSupportFragmentManager();

getChildFragmentManager()区别于getActivity().getSupportFragmentManager(),因为在Fragment中使用ViewPager显示多个Fragment,所以需要使用fragment中的FragmentManager;

如果使用getActivity().getSupportFragmentManager(),在ViewPager中的Fragment打开另一个Fragment时有两个问题:
(1)、两个Fragment的onCreateOptionsMenu都会被调用,从而导致被打开的Fragment的Toolbar菜单按钮点击事件失效,且会一起显示出来;
(2)、返回时,ViewPager中的Fragment的视图会为空,显示空白;

Fragment全解析系列(二):正确的使用姿势

节选自:Fragment全解析系列(二):正确的使用姿势


Fragment是可以让你的app纵享丝滑的设计,如果你的app想在现在基础上性能大幅度提高,并且占用内存降低,同样的界面Activity占用内存比Fragment要多,响应速度Fragment比Activty在中低端手机上快了很多,甚至能达到好几倍!如果你的app当前或以后有移植平板等平台时,可以让你节省大量时间和精力