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.空格替代符
名称 | 编号 | 描述 |
---|---|---|
|   | 不会被合并的空格,长度与常规空格相同 |
  |   | 全角空格,长度等于半个中文字符 |
  |   | 全角空格,长度等于一个中文字符 |
开发中可能会遇到要用空格对齐文字
密 码,中间有连续空格的,在资源文件中不管打多少个空格都只会显示一个空格
可使用空格的替代符号
替代符号就是在需要显示空格的地方加入替代符号,这些符号会被浏览器解释为空格显示。
“新 密 码”在资源文件中应该这样写的:新 密 码
“密 码”在资源文件中应该这样写的:密  码
首行空两格可以在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文件就进来啦.
网友评论