Ccixyj / KeepMove

vue教程:https://www.bilibili.com/video/av36650577

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Android开发中遇到的问题记录

Ccixyj opened this issue · comments

记录在Android开发的问题,包括kotlin
ia 3lknvka 29 pn a74 hl

1.Unresolved reference for synthetic view when layout is in library module (无效)

父模块使用子模块的布局,kotlin-android-extensions 是不能直接使用。

//配置文件添加如下:
androidExtensions {
    experimental = true
}

参考stackoverflow的问题
Kotlin Android Extensions的高级用法可以查阅官方文档

现在没有真正的解决办法
KT-22430

2. ConstraintLayout (1.1.x) 在 RecyclerView 中高度不正确的问题

ConstraintLayout 修改属性如下:

   android:layout_height="wrap_content"
   app:layout_constraintHeight_default="wrap"
   app:layout_constrainedHeight="true"

主要是 app:layout_constraintHeight_default="wrap" 这条属性

参考:

  1. https://developer.android.google.cn/reference/android/support/constraint/ConstraintLayout
  2. https://stackoverflow.com/questions/40850966/wrap-content-view-inside-a-constraintlayout-stretches-outside-the-screen

3. canvas drawtext() 方法的注意点

drawtext() 参数的 y 是一 文字的 baseline 为基准的。所以需要画文字背景时需要考虑 计算 fontMetricsdescent / ascent 参数.

3. webview 无法加载图片的问题

对于大家来讲WebView肯定很熟悉,因为我们在日常开发中经常用到它。所以对于它的一些基本用法我就不在这啰嗦了,直接进入正题。

我遇到的问题就是在使用WebView加载网页的时候图片不显示(我手机系统是5.1.1),当时出现这个问题我就想当然的以为,是不是给WebView少设置的什么东西。然后百度一下:

mWebview.getSettings().setJavaScriptEnabled(true);//启用js 
mWebview.getSettings().setBlockNetworkImage(false);//解决图片不显示

然后我检查了自己代码,这两句话也明明加了啊,这到底是什么鬼。后面我也加过其它的一些设置,依然没有用。难道是我的访问路径有问题吗,于是我随便找了带图片的网页,使用WebView加载了一下,哎呦我擦,图片显示没毛病啊。看来还真是我的访问路径有问题啊,但是别的都显示没问题,为什么就图片不显示呢。我跟踪断点把访问的路径复制了出来一看,我靠原来访问路径是https的呀。于是我就把矛头指向了https,简单来说,https就是http的安全版,它在http的基础上加入了ssl层。https协议在使用的时候需要申请一个安全证书,我就想是不是安全证书有问题,回头一想假如安全证书有问题,页面应该是直接显示空白才对。问题又出在哪,于是我把网页路径复制到了浏览器打开,然后查看了一下网页源码,发现图片的引用是http的,问题会不会就出在这呢。果然不出所料:

if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){
 settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}

于是在设置WebView的时候加上了这句话,果然问题解决了。在5.0以下的系统即使不加这句话,图片也可以正常显示,亲测有效。

4. CoordinatorLayout > CollapsingToolbarLayout 中 需要全屏的处理

  1. xml 中不要出现 android:fitsSystemWindows="true|false"
  2. 使用 ImmersionBar ,并且 设置 immersionBar.titleBar(mToolbar).init()

注意: 父类如统一初始化了 immersionBar 的话,则要添加 immersionBar.reset() 或者复写父类的实现使得 immersionBar 不要初始化

5. WebviewJS 交互 方式

使用JsPrompt方式拦截时** 需要记得调用 result?.confirmresult?.cancel()

参考:
Android:你要的WebView与 JS 交互方式 都在这里了

7. fragment 中 toolbar 的问题

一个 Activity 中含有多个fragment,且每个fragment有toolbar。那么每个fragment的toolbar是不同的实例,但是activity.setSupportActionBar() 后,activity 的 actionbar 只能持有最后设置的 toolbar 实例。

解决方案:

  1. 当前fragment 显示时再次设置activity.setSupportActionBar(),比如在 viewerpager 中。
  2. 去掉 fragment 中的 activity.setSupportActionBar() ,在各自的 fragment 完成各自的初始化,脱离与 activity 的联系。

相关问题:

  1. 关于在Fragment中使用ToolBar导致菜单错乱----惊现巨坑

8.SwipeRefreshLayout 与 CoordinatorLayout 嵌套刷新

嵌套刷新

Appbar相关 AppBarStateChangeListener

public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener {

    public enum State {
        EXPANDED,
        COLLAPSED,
        IDLE
    }

    private State mCurrentState = State.IDLE;

    @Override
    public final void onOffsetChanged(AppBarLayout appBarLayout, int i) {
        if (i == 0) {
            if (mCurrentState != State.EXPANDED) {
                onStateChanged(appBarLayout, State.EXPANDED);
            }
            mCurrentState = State.EXPANDED;
        } else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) {
            if (mCurrentState != State.COLLAPSED) {
                onStateChanged(appBarLayout, State.COLLAPSED);
            }
            mCurrentState = State.COLLAPSED;
        } else {
            if (mCurrentState != State.IDLE) {
                onStateChanged(appBarLayout, State.IDLE);
            }
            mCurrentState = State.IDLE;
        }
    }

    public abstract void onStateChanged(AppBarLayout appBarLayout, State state);
}

9. Toolbar 中 标题居中

确保添加了下面的属性:

 <android.support.v7.widget.Toolbar

      <TextView
       android:layout_width="wrap_content"      
       android:layout_gravity="center"
       android:gravity="center"  />

 </android.support.v7.widget.Toolbar>

10. ViewPager 嵌套 HorizontalScrollView 的滚动处理

自定义 ViewPager ,重写 canScroll()

override fun canScroll(v: View, checkV: Boolean, dx: Int, x: Int, y: Int): Boolean {
        return if (v is HorizontalScrollView) {
            val child = v.getChildAt(0) ?: return super.canScroll(v, checkV, dx, x, y)
            if (child.measuredWidth == v.scrollX + v.width - v.paddingLeft - v.paddingRight) {
                super.canScroll(v, checkV, dx, x, y)
            } else true
        } else super.canScroll(v, checkV, dx, x, y)
    }

其中,要注意 child.measuredWidth == v.scrollX + v.width - v.paddingLeft - v.paddingRight 是处理
滚到底部后触摸事件交还给 ViewPager 处理

参考:
Android ScrollView监听滑动到顶部和底部的两种方式(你可能不知道的细节)

11. ConstraintLayout 中 Group 的注意点

group.setGone 没问题。 但是 group.setInvisible 需要手动调用group.updatePreLayout(constraintLayout)
推测原因为 setInvisible 不会调用 updateLayout

12. GlideTransformation 注意点

GlideFitCenter CenterCrop 都属于 Transformation<T> 类型。如果要添加自定义的 Transformation 时,都需要放入 Transform(vararg transforms) 中。

示例:

//glide 3.x , 4.x 类似 
 Glide.with(this).load(img)
.bitmapTransform(  CenterCrop(viewContext), RoundedCornersTransformation(viewContext, 8, 0))
.into(imageview)

13. Webview (h5)中 video 全屏播放

在使用 webview ,如何让 video 支持全屏呢?

  1. 首先在对应的 activity 标签中条件旋转的支持。
      android:configChanges="orientation|keyboardHidden|navigation|screenSize"
      android:hardwareAccelerated="true"
      android:screenOrientation="portrait"

同时 在对应布局中添加一个占位 view container

<FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <WebView
            android:id="@+id/base_webView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <ProgressBar
            android:id="@+id/mp_web_progress"
            style="@style/Widget.AppCompat.ProgressBar.Horizontal"
            android:layout_width="match_parent"
            android:layout_height="@dimen/material_3dp"
            android:background="@color/transparent"
            android:max="100"
            android:padding="0dp" />

        <!--全屏占位的view container-->
        <FrameLayout
            android:id="@+id/fl_video"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="gone" />

    </FrameLayout>
  1. 确认添加了 WebSetting 相关配置
        webSettings.loadWithOverviewMode = true
  1. 自定义的 WebChromeClient 中复写 onShowCustomView(view: View?, callback: CustomViewCallback?)onHideCustomView() 方法
        private var nVideoView: View? = null
        private var customViewCallback: CustomViewCallback? = null

        override fun onShowCustomView(view: View?, callback: CustomViewCallback?) {
            super.onShowCustomView(view, callback)
            super.onShowCustomView(view, callback)
            if (nVideoView != null) {
                callback?.onCustomViewHidden()
                return
            }
            nVideoView = view
            nVideoView?.visibility = View.VISIBLE
            customViewCallback = callback
            // 占位view容器添加nVideoView
            fl_video?.addView(nVideoView)
            fl_video?.visibility = View.VISIBLE
            fl_video?.bringToFront()
            //设置横屏
            requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
            mToolbar.visibility = View.GONE
           immersionBar.fullScreen(true).transparentStatusBar().statusBarDarkFont(false).init()
        }


        // 退出全屏调用此函数
        override fun onHideCustomView() {
            if (nVideoView == null) {
                return
            }
            try {
                customViewCallback?.onCustomViewHidden()
            } catch (e: Exception) {
            }

            nVideoView?.visibility = View.GONE
            // 占位view容器移除nVideoView
            fl_video?.removeView(nVideoView)
            nVideoView = null
            fl_video?.visibility = View.GONE
            // 设置竖屏
            requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
            // 取消全屏
            val attrs = window.attributes
            attrs.flags = attrs.flags and WindowManager.LayoutParams.FLAG_FULLSCREEN.inv()
            window.attributes = attrs
            mToolbar.visibility = View.VISIBLE
          immersionBar.statusBarDarkFont(true, 0.12f).statusBarColor("#F7F7F7").init()
        }

完成。查看效果!!!

14.查看 android gradle 源码的一种方式

在 dependencies 加入 testImplementation "com.android.tools.build:gradle:${versions.gradle}" 即可

15.高德地图POI搜索多个类别

搜索多个类别。多个关键字用“|”分割 。

相关文档:PoiSearch.Query#构造函数

16.记录一个奇怪的bug,可能是混淆文件写的不正确

kotlin package级别的一个常量导致了android 在打包混淆 时某个依赖包的asstes 文件丢失一部分

private const val UnitTrans = 666.67
导致
nim_keystore
nim_keystore2
丢失
...

17. NestedScrollView 键盘遮挡的一个解决方案(adjustpan 无效)

项目里可以获取到 keybord 的高度。而且 adjustpan 无效,且 EditTextNestedScrollView底部,所以解决方案如下:

  1. 键盘弹出时添加一个 keybord 高度的 Space,并滑动只底部
setOnKeyboardListener { isPopup, keyboardHeight ->
            KLog.d("setOnKeyboardListener $isPopup $keyboardHeight")
         if (isPopup){
             if (fr is MeetDetailFragment){
                 if (space.parent != null){
                     return@setOnKeyboardListener
                 }
                 space.apply {
                     layoutParams = ViewGroup.MarginLayoutParams(0, keyboardHeight)
                 }
                 //post to queue
                 fr.ll_meet_body.addView(space)
                 fr.nsc_meet_parent?.post {
                     fr.nsc_meet_parent.fullScroll(View.FOCUS_DOWN)
                 }
             }
         }else{
             if (fr is MeetDetailFragment){
                 fr.ll_meet_body.removeView(space)
             }
         }
  1. 键盘关闭时添加一个移除 Space

https://blog.csdn.net/HJF_HUANGJINFU/article/details/61199480

18. 一行代码帮你检测Android模拟器

https://www.jianshu.com/p/434b3075b5dd

强制刷新app的依赖

gradlew build --refresh-dependencies

阿里云推送的坑

Android集成阿里云推送时,如果使用IntentService时,同时也要集成MessageReceiver,否则在进程结束后再次打卡app收不到离线的信息!!!

Drawable 多次tint时的问题

DrawableCompat.wrap(drawable) 后tint 需要先 unwrap
DrawableCompat.unwrap<Drawable>(drawable)

Android O

1. Service 使用 ContextCompat.startForegroundService(this,serIntent)

ForegroundService 需要构造一个 notification 来确保为前台服务
startForeground( i > 0 , notification)

notification 至少需要 setContentTitlesetSmallIcon

ADB 操作

1 . adb shell am start -n "package/package+classname"
2. adb shell am force-stop "package"