前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android Notes|实用小技巧,不定期更新...

Android Notes|实用小技巧,不定期更新...

原创
作者头像
贺biubiu
发布2024-03-26 11:50:33
500
发布2024-03-26 11:50:33
举报
文章被收录于专栏:HLQ_StruggleHLQ_Struggle

还是老规矩,小图镇楼~

小厂开发而言,日常的繁杂的业务开发任务相对较重,有些东西,首次遇到,后续也不想再浪费时间。

一直想做一个积累,一个笔记,一个总结,将日常开发中遇到的小细节记录在案,方便查阅,也能方便帮助其他小伙伴~

还是没等到掘金上线图片水印开关,先发文,后更新啦~

有不对地方欢迎大佬指点~

View 篇章

Shape

layer-list 定义图片

假设 UI 仅提供中间沙发 logo,如何构建如下 UI 效果图?

首先构建外层圆形背景图:

代码语言:java
复制
    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="oval">
        <size
            android:width="@dimen/dimen_90_dp"
            android:height="@dimen/dimen_90_dp" />
        <solid android:color="@color/color_2d0d52" />
    </shape>

合并生成一张图:

代码语言:java
复制
    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/shape_circle_2d0d52" />
        <item
            android:drawable="@drawable/ic_guard_sofa"
            android:gravity="center" />
    </layer-list>

shape 搭配 layer-list 实现边框样式

文字描述不是很清晰,直接看效果图吧:

注意观察,只有底部没有边框~

先实现底层 shape:

代码语言:java
复制
    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
        <corners android:radius="@dimen/dimen_20_dp" />
        <gradient
            android:angle="120"
            android:endColor="@color/color_cf77de_00"
            android:startColor="@color/color_b573d8"
            android:type="linear" />
    </shape>

效果如下:

随后编辑上层 shape:

代码语言:java
复制
    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
        <corners android:radius="@dimen/dimen_20_dp" />
        <gradient
            android:angle="180"
            android:endColor="@color/color_5a13a2"
            android:startColor="@color/color_6f1e94"
            android:type="linear" />
    </shape>

效果如下:

两者结合,孕育新生:

代码语言:java
复制
    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/shape_b573d8_00cf77de" />
        <item
            android:bottom="-2dp"
            android:drawable="@drawable/shape_6f1e94_5a13a2"
            android:left="@dimen/dimen_1_dp"
            android:right="@dimen/dimen_1_dp"
            android:top="@dimen/dimen_1_dp" />
    </layer-list>

ConstraintLayout

动态设置约束(适用于需要调整单个情况)

代码语言:jvm
复制
fun adjustKtvImChatInParentRoot(imChatView: View) {
    val layoutParams = imChatView.layoutParams
    if (layoutParams is ConstraintLayout.LayoutParams) {
        layoutParams.reset()  // 重置布局参数
        layoutParams.topToTop = R.id.imChatSpace
        layoutParams.bottomToBottom = R.id.imChatSpace
        layoutParams.startToEnd = R.id.imChatSpace
    }
}

动态设置约束(适用于需要调整多个情况)

代码语言:java
复制
fun resetVIPPosition(csRoot: ConstraintLayout) = ConstraintSet().apply {  // 动态设置约束的合集
    clone(csRoot)   // 克隆父布局约束
    clear(R.id.vip_view_fl, END)   // 移除指定约束
    connect(R.id.vip_view_fl, TOP, R.id.view_flipper, BOTTOM, 10.dp)   // top_bottom margin 10
}.applyTo(csRoot)                       // 应用约束

简单说下步骤吧:

  • 首先通过 clone 进行父布局克隆;
  • 随后可以通过 clear 清除 view 指定约束,前者为 view id,后者为约束位置,上右下左;
  • 最后可以通过 connect 设置对应的约束即可,参数依次为:当前 view id,对其约束位置,目标 view id,对其约束位置,margin

动态设置比例

xml 布局中通过如下设置比例:

代码语言:jvm
复制
app:layout_constraintDimensionRatio="900:1170"

代码中则可以通过如下方式:

代码语言:jvm
复制
ConstraintSet().apply {
    clone(prettyParentCl)   <--- 根布局 id
    setDimensionRatio(
        R.id.buyPrettyNumIv,  <--- 要调整的 View Id
        if (mIsBindPrettyNum) "900:990" else "900:1170"  <--- 调整后的比例
    )
}.applyTo(prettyParentCl)   <--- 根布局 id

TextView

内部可滑动

xml 设置滑动方向:

代码语言:jvm
复制
android:scrollbars="vertical"

代码中设置 mode:

代码语言:jvm
复制
textView.movementMethod = ScrollingMovementMethod.getInstance()

一个 TextView 实现 drawable + 文字效果

如下图所示:

实现重点:

  • TextView 宽度自适应;
  • 设置 DrawPadding;
  • 设置 Padding

代码设置加粗

代码语言:jvm
复制
findViewById<TextView>(R.id.comm_indicator_txt).apply { 
    paint.isFakeBoldText = true     // 加粗 
}

代码设置 selector color

代码语言:jvm
复制
setTextColor(ContextCompat.getColorStateList(context, [selector resid]))

代码设置 drawable/LTRB/Padding

Way 1: 通过 setCompoundDrawables 方式

代码语言:jvm
复制
private fun TextView.setCardOperateDrawable(resId: Int) { 
    val drawable = ContextCompat.getDrawable(mContext, resId)?.apply { 
        // 必须设置 Bounds 否则 drawable 不显示 
        setBounds(0, 0, minimumWidth, minimumHeight) 
    }  
    compoundDrawablePadding = drawablePadding  
    setCompoundDrawables(drawable, null, null, null) 
}

Way 2: 通过 setCompoundDrawablesRelativeWithIntrinsicBounds 方式

代码语言:jvm
复制
sudGameOperatorAudioTxt.apply { 
    // ... 
    setCompoundDrawablesRelativeWithIntrinsicBounds( 
        if (mAudioOperatorStatus) R.drawable.xxx else R.drawable.xxx, 
        0, 
        0, 
        0 
    ) 
}

代码设置 drawable 并指定宽高

公共方法抽离:

代码语言:jvm
复制
fun getDrawable(context: Context, resId: Int, right: Int = -1, bottom: Int = -1): Drawable? =   
    ContextCompat.getDrawable(context, resId)?.apply {   
    // 必须设置 Bounds 否则 drawable 不显示   
    setBounds(   
    0,   
    0,   
    if (right == -1) minimumWidth else right,   
    if (bottom == -1) minimumHeight else bottom   
    )   
}

具体设置案例:

代码语言:jvm
复制
private fun resetStatusRes(filterTxt: TypeFontTextView, drawableRes: Int = -1) {   
    val defaultRes = if (drawableRes == -1) R.drawable.ic_filter_nor else drawableRes   
    val iconDrawable = getDrawable(mContext, defaultRes, 10.dp, 10.dp)   
    filterTxt.setCompoundDrawables(null, null, iconDrawable, null)   
}

在文字后追加一个图片

代码语言:jvm
复制
binding.contractDetailOathTxt.apply {   
    val oathStr = "" 
    val spannableString = SpannableString(oathStr)   
    val drawable = resources.getDrawable(R.drawable.icon_edit_white, null)   
    val resizedBitmap = resizeBitmap(drawableToBitmap(drawable), 14.dp, 14.dp)   
    val imageSpan =   
        ImageSpan(context, resizedBitmap, DynamicDrawableSpan.ALIGN_BOTTOM)   
    spannableString.setSpan(   
        imageSpan,   
        oathStr.length - 1,   
        oathStr.length,   
        Spannable.SPAN_INCLUSIVE_EXCLUSIVE   
    )   
    text = spannableString 

设置文字竖向展示

代码语言:jvm
复制
android:ems="1"

ems: 代表当前一行可设置几个字符。

文字超链接点击后,背景色如何消除

代码语言:jvm
复制
highlightColor = R.color.trans.ColorInt

跑马灯效果

xml 布局中设置如下:(注意宽度要限制)

代码语言:jvm
复制
android:ellipsize="marquee"  
android:marqueeRepeatLimit="marquee_forever" 
android:singleLine="true"

代码中设置 isSelected = true 即可。

RecyclerView

多点触控导致 item 多次触发

大概的就是就是,因为多点触控的关系,导致多个手指点击后,item 执行了多个操作(可能描述不太准确)。

解决方案:

  • 给 RecycerView 添加 android:splitMotionEvents="false"

禁止滑动阴影

代码语言:jvm
复制
android:overScrollMode="never"

监听滑动并获取当前 item 位置(针对滑动)

代码语言:jvm
复制
addOnScrollListener(object : RecyclerView.OnScrollListener() { 
    override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { 
        super.onScrollStateChanged(recyclerView, newState) 
        if (recyclerView.scrollState == SCROLL_STATE_IDLE) { 
            (recyclerView.layoutManager as Your Use LayoutManager).findFirstVisibleItemPosition()  
        } 
    } 

EditText

限制输入字符/字节数量

一直使用的 length 长度,便是实际输入长度,而这里的字符数,则代表字节数。

例如 GBK 编码下一个汉字占据两个字节,而 UTF-8 编码下一个汉字占据三个字节。

用户输入的字节长度,可以用以下方式获取:

  • inputStr?.toByteArray(Charset.forName("GBK")).size

下面贴出关键代码:

代码语言:jvm
复制
private val mNikeNameTextWatcher = object : TextWatcherAdapter { 
    override fun afterTextChanged(s: Editable?) { 
        super.afterTextChanged(s) 
        et_content.getEditTextView().removeTextChangedListener(this) 
        val inputStr = s?.toString()?.trim() 
        val bytes = inputStr?.toByteArray(Charset.forName("GBK")) 
        if ((bytes?.size ?: 0) > 16) { 
            toast("超出规定字符数,请按要求填写") 
            bytes?.let { 
                val newBytes = ByteArray(16) 
                System.arraycopy(it, 0, newBytes, 0, newBytes.size) 
                val resultText = String(newBytes, Charset.forName("GBK")) 
                et_content.setEditTextContent(resultText) 
                Selection.setSelection( 
                    et_content.getEditTextView().editableText, 
                    resultText.length 
                ) 
            } 
        } 
        et_content.getEditTextView().addTextChangedListener(this) 
    } 
}

设置密码可见/隐藏

密码明文展示:

代码语言:jvm
复制
setTransformationMethod(HideReturnsTransformationMethod.getInstance())

密码脱敏展示:

代码语言:jvm
复制
setTransformationMethod(PasswordTransformationMethod.getInstance())

记得更新光标位置:

代码语言:jvm
复制
setSelection(mEtCode.getText().length())

ViewPager2

禁止滑动

代码语言:jvm
复制
isUserInputEnabled = false

ScrollView

滚动到底部

代码语言:jvm
复制
roleScrollView.post { 
    roleScrollView.fullScroll(View.FOCUS_DOWN) 
}

Button

取消默认英文大写

代码语言:jvm
复制
android:textAllCaps="false"

Toolbar

取消左侧默认边距

代码语言:jvm
复制
app:contentInsetLeft="@dimen/dimen_0_dp" 
app:contentInsetStart="@dimen/dimen_0_dp"

LottieAnimationView

设置默认播放进度

代码语言:jvm
复制
loadingLottie.progress = 0.5f

AppBarLayout

取消底部阴影

代码语言:jvm
复制
app:elevation="0dp"

注意是 app 下,并不是 android 下!!!

Style

style 不支持自定义属性或者非 android 命名空间抽离,如何处理?

直接在 name 中写对应的属性即可。

代码语言:jvm
复制
<style name="commUserProfileSeeMoreStyle">    
    <item name="drawableRightCompat">@drawable/icon_arrow_right_gray</item> 
</style>

无需申请权限开启震动反馈

代码语言:jvm
复制
view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)

日常开发小细节

金额超限,显示科学计数法,如何处理?

金额类型替换为 BigDecimal

例 1:A 除以 B 并保留两位小数
代码语言:jvm
复制
money.divide(BigDecimal(100), 2, BigDecimal.ROUND_DOWN).toString(), // 金额 元 

Error 汇总

java.lang.IllegalArgumentException: Parameter type must not include a type variable or wildcard:...(parameter #1)

Service 接口方法上追加 @JvmSuppressWildcards

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • View 篇章
    • Shape
      • layer-list 定义图片
      • shape 搭配 layer-list 实现边框样式
    • ConstraintLayout
      • 动态设置约束(适用于需要调整单个情况)
      • 动态设置约束(适用于需要调整多个情况)
      • 动态设置比例
    • TextView
      • 内部可滑动
      • 一个 TextView 实现 drawable + 文字效果
      • 代码设置加粗
      • 代码设置 selector color
      • 代码设置 drawable/LTRB/Padding
      • 代码设置 drawable 并指定宽高
      • 在文字后追加一个图片
      • 设置文字竖向展示
      • 文字超链接点击后,背景色如何消除
      • 跑马灯效果
    • RecyclerView
      • 多点触控导致 item 多次触发
      • 禁止滑动阴影
      • 监听滑动并获取当前 item 位置(针对滑动)
    • EditText
      • 限制输入字符/字节数量
      • 设置密码可见/隐藏
    • ViewPager2
      • 禁止滑动
    • ScrollView
      • 滚动到底部
    • Button
      • 取消默认英文大写
    • Toolbar
      • 取消左侧默认边距
    • LottieAnimationView
      • 设置默认播放进度
    • AppBarLayout
      • 取消底部阴影
    • Style
      • style 不支持自定义属性或者非 android 命名空间抽离,如何处理?
    • 无需申请权限开启震动反馈
      • 金额超限,显示科学计数法,如何处理?
  • 日常开发小细节
  • Error 汇总
    • java.lang.IllegalArgumentException: Parameter type must not include a type variable or wildcard:...(parameter #1)
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档