美文网首页
Android小知识汇总

Android小知识汇总

作者: 青果果 | 来源:发表于2017-11-29 10:09 被阅读0次

    1.ScrollView相关

    问题1.有ScrollView的布局,进入页面时会自动滑动

    在ScrollView父布局写 android:focusableInTouchMode="true"

    参考:从源码剖析原理及解决方式

    问题2.ScrollView和ListView嵌套

    http://blog.csdn.net/insist_onzw/article/details/74857925
    http://blog.csdn.net/liaoinstan/article/details/50509122

    ListView源码onMeasure()方法中
    ListView的父容器测量模式为UNSPECIFIED的时候
    ListView的高度默认为一个item的高度

    //ListView的父容器测量模式为UNSPECIFIED的时候,ListView的高度默认为一个item的高度
    //代码是源码其中一部分,有省略
    if (heightMode == MeasureSpec.UNSPECIFIED) {
        heightSize = mListPadding.top + mListPadding.bottom + childHeight +
                       getVerticalFadingEdgeLength() * 2;
    }
    

    那我们再看看ScrollView源码里面是什么样的

     @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            if (!mFillViewport) {//源码debug这里会直接return
                return;
            }
            final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            if (heightMode == MeasureSpec.UNSPECIFIED) {
                return;
            }
    }
    

    那继续看SrcollView的父类FrameLayout的onMeasure做了什么

     @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int count = getChildCount();
    
            final boolean measureMatchParentChildren =
                    MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY ||
                    MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY;
            mMatchParentChildren.clear();
    
            int maxHeight = 0;
            int maxWidth = 0;
            int childState = 0;
    
            for (int i = 0; i < count; i++) {
                final View child = getChildAt(i);
                if (mMeasureAllChildren || child.getVisibility() != GONE) {
                    measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);//这个方法
                    final LayoutParams lp = (LayoutParams) child.getLayoutParams();
                    maxWidth = Math.max(maxWidth,
                            child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
                    maxHeight = Math.max(maxHeight,
                            child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
                    childState = combineMeasuredStates(childState, child.getMeasuredState());
                    if (measureMatchParentChildren) {
                        if (lp.width == LayoutParams.MATCH_PARENT ||
                                lp.height == LayoutParams.MATCH_PARENT) {
                            mMatchParentChildren.add(child);
                        }
                    }
                }
            }
    

    ScrollView有重写这个方法measureChildWithMargins()
    可看到ScrollView给子类的测量MODE都是UNSPECIFIED
    所以ScrollView嵌套ListView的时候只会显示一个item

     @Override
        protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed,
                int parentHeightMeasureSpec, int heightUsed) {
            final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
    
            final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
                    mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
                            + widthUsed, lp.width);
            final int usedTotal = mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin +
                    heightUsed;
            final int childHeightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(
                    Math.max(0, MeasureSpec.getSize(parentHeightMeasureSpec) - usedTotal),
                    MeasureSpec.UNSPECIFIED);//重点来了,看到了给子类的测量MODE都是UNSPECIFIED
    
            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
        }
    

    那么ScrollView嵌套LinearLayout再嵌套ListView
    看看LinearLayout源码竖直方向布局的时候 测量方法

    void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {
           
                    // Determine how big this child would like to be. If this or
                    // previous children have given a weight, then we allow it to
                    // use all available space (and we will shrink things later
                    // if needed).
     final int usedHeight = totalWeight == 0 ? mTotalLength : 0;
    measureChildBeforeLayout(child, i, widthMeasureSpec, 0,heightMeasureSpec, usedHeight);
    
     void measureChildBeforeLayout(View child, int childIndex,
                int widthMeasureSpec, int totalWidth, int heightMeasureSpec,
                int totalHeight) {
            measureChildWithMargins(child, widthMeasureSpec, totalWidth,
                    heightMeasureSpec, totalHeight);
        }
    
    //LinearLayout并没有重写ViewGroup的方法measureChildWithMargins
      protected void measureChildWithMargins(View child,
                int parentWidthMeasureSpec, int widthUsed,
                int parentHeightMeasureSpec, int heightUsed) {
            final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
    
            final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
                    mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
                            + widthUsed, lp.width);
            final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
                    mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin
                            + heightUsed, lp.height);
    
            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
        }
    
    ViewGroup的getChildMeasureSpec方法
    public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
    case MeasureSpec.UNSPECIFIED:
                if (childDimension >= 0) {
                    // Child wants a specific size... let him have it
                    resultSize = childDimension;
                    resultMode = MeasureSpec.EXACTLY;
                } else if (childDimension == LayoutParams.MATCH_PARENT) {
                    // Child wants to be our size... find out how big it should
                    // be
                    resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
                    resultMode = MeasureSpec.UNSPECIFIED;
                } else if (childDimension == LayoutParams.WRAP_CONTENT) {
                    // Child wants to determine its own size.... find out how
                    // big it should be
                    resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
                    resultMode = MeasureSpec.UNSPECIFIED;
                }
    

    2.TextView相关

    一些比较少用的属性

    1、android:lineSpacingExtra //设置行间距,如”8dp”
    2、android:lineSpacingMultiplier //设置行间距的倍数,如”1.5″
    3、android:ellipsize="end"//文字省略

    3.RatingBar相关

    问题1:要显示半颗星,必须设置secondaryProgress

        <item
            android:id="@+android:id/progress"
            android:drawable="@drawable/evaluate_ratingbar_s">
        </item>
    
        <item
            android:id="@+android:id/secondaryProgress"
            android:drawable="@drawable/evaluate_ratingbar_half">
        </item>
    

    android:numStars="5" //星星总数
    android:rating="3.5" //默认值设置星星个数
    android:stepSize="0.5"//步进值

    4.PopupWindow相关

    问题1:Android7.0显示 PopupWindow位置错误

    用showAsDropDown()这个方法,让pop显示在某个View的下面,而且pop的高度是match_parent的话,其显示的位置在Android7.0以下系统正常,在7.0和7.1系统显示不正常,会全屏显示盖着整个页面

    问题2:PopupWindow需要设置背景点击外部才消失

    在6.0以下 需要设置背景点击外部才消失,6.0以后不需要设置

    setBackgroundDrawable(Drawable background)
    

    参考:
    从源码剖析PopupWindow 兼容Android 6.0以上版本点击外部不消失
    不得不吐槽的Android PopupWindow的几个痛点
    PopupWindow 点击外部和返回键无法消失背后的真相

    5.ListView相关

    问题1.ListView和ScrollView嵌套

    问题2.ListView去掉点击水波纹效果,只展示数据

    有时候可能listview只是展示数据而已,item并不需要响应点击,也不需要点击效果
    那么就可以给listview设置属性

    android:listSelector="@android:color/transparent"
    

    6.空格替代符

    名称 编号 描述
    &nbsp; &#160; 不会被合并的空格,长度与常规空格相同
    &ensp; &#8194; 全角空格,长度等于半个中文字符
    &emsp; &#8195; 全角空格,长度等于一个中文字符

    开发中可能会遇到要用空格对齐文字
    密  码,中间有连续空格的,在资源文件中不管打多少个空格都只会显示一个空格

    可使用空格的替代符号
    替代符号就是在需要显示空格的地方加入替代符号,这些符号会被浏览器解释为空格显示。
    “新 密 码”在资源文件中应该这样写的:新&#8194;密&#8194;码
    “密  码”在资源文件中应该这样写的:密&#8195;&#8195;码

    首行空两格可以在java代码用: \u3000\u3000
    表示的是: 中文(全角)空格
    解释:\uxxxx
    其中xxxx表示一个16进制数字 这种格式是unicode码的写法表示一个char字符

    那就顺便再讲下占位符的使用
    有时候我们需要动态修改Android中strings.xml文件中的值
    strings.xml中节点是支持占位符的,如下所示:
    <string name="name">整数型:%1$d,浮点型:%2$.2f,字符串:%3$s</string>
    %后面是占位符的位置,从1开始(比如这里用到了三个占位符,从1开始往后排)
    $ 后面是填充数据的类型
    %d:表示整数型;
    %f :表示浮点型,其中f前面的.2表示小数的位数
    %s:表示字符串

    代码实现:

    //XML 文件中这样写
     <string name="book">书名:《%1$s》,作者:%2$s,编号(整数):%3$d,价格(浮点):%4$.2f元</string> 
    //代码中这样设置,需要一 一 对应
    textview.setText(String.format(getResources().getString(R.string.book),"金瓶梅", "西门庆", 2249, 88.3f));
    

    7.JNI是什么?

    Android系统的底层库是由c/c++编写,上层Android应用程序和应用程序框架通过JNI(JavaNative Interface)调用底层接口.

    Android使用JNI开发分两种情况:一是使用已经编译好的.so动态库;二是使用c/c++源代码开发.

    一些第三方的库出于性能或代码安全的目的,会将核心代码用C/C++来实现,然后提供编译好的so文件或jar包给我们.

    so文件是什么?

    Android中用到的so文件是一个c++的函数库,apk或jar包中调用so文件时,需要将对应so文件打包进apk或jar包.

    如何加载so文件?**

    假设你的so文件为:libBaiduMapSDK_v350_1.so

    这样加载:

    String libName = "BaiduMapSDK_v350_1"; // 注意:库名libName, 没有前缀lib和后缀.so

    System.loadLibrary( libName ); //在使用前一定要先加载

    so文件应该放在哪里?

    在Eclipse中我们将so文件放到libs目录下就可以了, 那么在AndroidStudio中应该将so文件放到哪里呢?

    放到moduleName/src/main/jniLibs目录下,如果没有jinLibs目录就新建一个.

    armeabi、armeabi-v7a、mips、x86这四个文件夹是干嘛的呢?

    表示四种不同的cpu类型,不同的cpu的特性不一样,在使用so文件时注意区分.

    可以直接复制so文件粘贴到对应的文件夹下

    ok之后so文件就进来啦.

    相关文章

      网友评论

          本文标题:Android小知识汇总

          本文链接:https://www.haomeiwen.com/subject/jsqubxtx.html