Android view.settran,View源码——android:XX属性

基于api28

常用属性不再赘述,只看一些不常用的或者新添加的属性。

1 padding

android:paddingHorizontal //同时设置左右padding

android:paddingVertical //同时设置上下padding

以上属性api26添加。

2 scroll

android:scrollX

android:scrollY

以上两个属性对应的成员变量为mScrollX mScrollX,在绘制之前,会执行

canvas.translate(-mScrollX, -mScrollY);

同时影响当前View的绘制,及其children的绘制。但对当前view的背景没有影响!

偏移量 > 0, 内容向右下偏移;

偏移量 < 0, 内容向左上偏移。

注:在xml中设置View的继承类的android:scrollX、android:scrollY不一定起作用,依赖于具体的实现。

比如ScrollView,由于在滚动时会判断getChildCount() > 0,而初始化时还没有子View,所以不起作用。

如下图为自定义的View,背景为黑色,在onDraw方法中画了一个圆,宽高均为100dp:

04df7e736fa4

图1 原图

设置android:scrollX=-50dp,背景不移动,内容右移:

04df7e736fa4

图2 android:scrollX=-50dp

至于为什么不影响背景,后续再学习。

3 matrix变换

android:transformPivotX

android:transformPivotY

android:rotation

android:rotationX

android:rotationY

android:translationX

android:translationY

android:translationZ

android:scaleX

android:scaleY

对图2设置如下属性:

android:transformPivotX="50dp"

android:transformPivotY="50dp"

android:rotation="30"

android:scaleX="0.8"

android:translationX="30dp"

显示如下:

04df7e736fa4

图3 matrix变换

蓝色方框是matrix变换之前的位置。

为当前View设置点击事件,可以发现,仅在点击View的绘制区域(非白色区域)时触发onClick方法,在点击蓝色方框内的空白区域时不会触发。

有以下结论:

matrix变换影响整个View的显示(包括子View)

matrix与scrollX srollY互不影响

matrix会影响可点击区域

有的同学还知道有个android:elevation属性,它和android:translationZ有什么区别呢?

android系统中,View所在的坐标系是一个三维的,View最终的坐标可以通过getX getY getZ三个方法得到。看一下这三个方法的实现:

public float getX() {

return mLeft + getTranslationX();

}

public float getY() {

return mTop + getTranslationY();

}

public float getZ() {

return getElevation() + getTranslationZ();

}

为了便于理解,我们可以将mLeft mTop elevation看做是View本身的坐标值,translationX tranlationY tranlationZ看做是偏移量。则 最终坐标 = 坐标值 + 偏移量。

而x y z的set方法设置的就是偏移量:

public void setX(float x) {

setTranslationX(x - mLeft);

}

public void setY(float y) {

setTranslationY(y - mTop);

}

public void setZ(float z) {

setTranslationZ(z - getElevation());

}

4 fitsSystemWindows

android:fitsSystemWindows

5 saveEnabled

android:saveEnabled

设置View是否意外销毁时,会调用onSaveInstanceState方法来保存状态。默认为true。详见View源码——saveInstanceState

6 duplicateParentState

设置当前view是否使用父view的状态,默认false。该状态主要影响drawable的显示。View源码——duplicateParentState

7 滚动相关

以如下布局为例:

android:id="@+id/scroll"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#ffc">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="vertical">

android:id="@+id/emotion1"

android:layout_width="match_parent"

android:layout_height="900dp"

android:background="#9c9"

android:gravity="center"

android:scrollX="30dp"

android:text="TextView"

android:textSize="19dp" />

此时的ui是这个样子的:

04df7e736fa4

图4

1、ScrollView添加两个属性:

android:id="@+id/scroll"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:fadingEdgeLength="50dp"

android:requiresFadingEdge="vertical"

android:background="#ffc">

04df7e736fa4

图5

scrollview的背景是米黄色。可以看到,在可以滑动的边上,呈现出淡出的效果。

2、android:scrollbarSize控制滚动条的尺寸。

android:scrollbarStyle控制滚动条的风格。有四个值:insideOverlay,insideInset,outsideOverlay,outsideInset。

为了方便区分这四个风格,我们为ScrollView设置一个30dp的padding, 同时scrollbarSize设置为30dp。四种风格如下:

04df7e736fa4

图6 insideOverlay

04df7e736fa4

图7 insideInset

04df7e736fa4

图8 outsideOverlay

04df7e736fa4

图9 outsideInset

3、android:overScrollMode控制scrollView滑到头时,是否显示阴影。图4可以很明显看出来滑到头时的阴影部分。有三个取值:

never: 从不显示

always:滑到头时显示

ifContentScrolls(默认):若内容过短,scrollView无法滑动,则不显示;否则显示。

4、android:isScrollContainer与软键盘有关。参考android:isScrollContainer 属性的作用

5、android:verticalScrollbarPosition 垂直滚动条的显示位置,有三个值:left right defaultPosition,很简单不再多说。

8 android:filterTouchesWhenObscured

view被其他窗口遮挡时,是否过滤触摸事件。默认false。只看说明很难理解,下面看一个例子。

布局:

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@android:color/white"

android:gravity="center_horizontal"

android:orientation="vertical">

android:layout_width="match_parent"

android:layout_height="wrap_content">

android:id="@+id/bt1"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:onClick="onClick"

android:text="toast"

android:textAllCaps="false" />

java

public class ViewActivity extends Activity implements View.OnClickListener {

private View view;

@Override

protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_view);

view = new View(getApplicationContext());

view.setBackgroundColor(0x88000000);

WindowManager.LayoutParams params = new WindowManager.LayoutParams();

params.width = 720;

params.gravity = Gravity.LEFT | Gravity.TOP;

params.format = PixelFormat.TRANSPARENT;

params.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;

getWindowManager().addView(view, params);

}

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.bt1:

Toast.makeText(this, "hahha", Toast.LENGTH_SHORT).show();

break;

default:

break;

}

}

@Override

protected void onDestroy() {

super.onDestroy();

getWindowManager().removeView(view);

}

}

代码很简单,在activity的页面上盖了一个window。如下:

04df7e736fa4

图10

透明黑色的部分是盖的新的window,由图可知,按钮被window遮挡的部分也可以响应点击事件。

现在我们给根布局LinearLayout(按钮本身或包含它的布局都可以)加上android:filterTouchesWhenObscured="true"

04df7e736fa4

图11

从图11可以看到,按钮被遮挡的部分,已经不再响应点击事件了。

9 android:stateListAnimator

关于这个属性的讲解有很多,不再赘述

10 outline相关

api21开始才有的。api21之后,view添加elevation、transitionZ的方法,由二维空间变成了三维空间。在Z轴上,可以通过outline来为view设置阴影等。

xml文件可以设置以下三个属性:

android:outlineAmbientShadowColor

android:outlineSpotShadowColor

android:outlineProvider

第一个用来设置环境光颜色,不过肉眼难以分辨。默认黑色。

第二个用来设置阴影的主题颜色。默认黑色。

第三个设置outline的获取方式,分别为:background(默认)、none、bounds、paddedBounds。区别下面会讲。

先看个例子:

xml

android:id="@+id/image"

android:layout_width="300dp"

android:layout_height="wrap_content"

android:adjustViewBounds="true"

android:outlineProvider="bounds"

android:outlineSpotShadowColor="#f00"

android:src="@drawable/sss"

android:translationZ="60px" />

04df7e736fa4

图12 outline阴影效果

android:outlineProvider对应的java方法为:

public void setOutlineProvider(ViewOutlineProvider provider) {

mOutlineProvider = provider;

invalidateOutline();

}

ViewOutlineProvider类很简单:

public abstract class ViewOutlineProvider {

public abstract void getOutline(View view, Outline outline);

}

android:outlineProvider的四个值,对应四个默认的ViewOutlineProvider。

background(默认):

public static final ViewOutlineProvider BACKGROUND = new ViewOutlineProvider() {

@Override

public void getOutline(View view, Outline outline) {

Drawable background = view.getBackground();

if (background != null) {

background.getOutline(outline);

} else {

outline.setRect(0, 0, view.getWidth(), view.getHeight());

outline.setAlpha(0.0f);

}

}

};

none则为null。

bounds:

public static final ViewOutlineProvider BOUNDS = new ViewOutlineProvider() {

@Override

public void getOutline(View view, Outline outline) {

outline.setRect(0, 0, view.getWidth(), view.getHeight());

}

};

paddedBounds:

public static final ViewOutlineProvider PADDED_BOUNDS = new ViewOutlineProvider() {

@Override

public void getOutline(View view, Outline outline) {

outline.setRect(view.getPaddingLeft(),

view.getPaddingTop(),

view.getWidth() - view.getPaddingRight(),

view.getHeight() - view.getPaddingBottom());

}

};

此外,view还有一个setClipToOutline的方法,可以根据outline裁剪内容

对上面的例子,在java代码中设置:

ImageView vImage = findViewById(R.id.image);

vImage.setClipToOutline(true);

vImage.setOutlineProvider(new ViewOutlineProvider() {

@Override

public void getOutline(View view, Outline outline) {

outline.setOval(new Rect(0, 0, view.getHeight(), view.getHeight()));

}

});

04df7e736fa4

图13

需要注意的是,这里只影响显示的内容,不影响点击区域。

同时,也不是任意的outline形状都支持裁剪。只有矩形、圆角矩形、圆形这三种支持。其他形状,包括椭圆都不支持。Outline类的方法canClip()可获取当前outline是否支持裁剪。其他设置方法可查看Outline类源码。

11 android:tooltipText

api26新加。给view设置一个功能提示。与电脑软件中,鼠标停留在一个按钮上,会弹出一个功能说明一样。这里通过长按触发。

如下面的TextView:

04df7e736fa4

图14

12 android:keyboardNavigationCluster

api26新增

04df7e736fa4

图15

13自动填充

api26新增的自动填充功能,目前使用很少,不再介绍。

没搞明白的几个

android:scrollIndicators

ViewGroup的属性

1 android:clipChildren

该属性默认是true

看这样一个布局:

android:id="@+id/btLayout"

android:layout_width="match_parent"

android:layout_height="wrap_content">

android:layout_width="100dp"

android:layout_height="100dp">

android:id="@+id/bt1"

android:layout_width="300dp"

android:layout_height="wrap_content"

android:focusedByDefault="true"

android:onClick="onClick"

android:text="按钮"

android:textAllCaps="false"

android:visibility="visible" />

打开开发者模式的布局边界开关,显示如下:

04df7e736fa4

图16

在外层的FrameLayout上加上android:clipChildren="false",显示如下:

04df7e736fa4

图17

该属性对应的java方法如下:

public void setClipChildren(boolean clipChildren) {

boolean previousValue = (mGroupFlags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN;

if (clipChildren != previousValue) {

setBooleanFlag(FLAG_CLIP_CHILDREN, clipChildren);

for (int i = 0; i < mChildrenCount; ++i) {

View child = getChildAt(i);

if (child.mRenderNode != null) {

child.mRenderNode.setClipToBounds(clipChildren);

}//child在绘制时,也会自行调用setClipToBounds方法

}

invalidate(true);

}

}

该方法只会影响直接子view。最终调用的是RenderNode的setClipToBounds方法。setClipToBounds方法会根据view的边界对显示区域进行裁剪。

RenderNode后续再讲。感兴趣的同学也可以查询其他资料。也可以把它暂时看做是canvas。

上例中,图16的显示应该不必说了。关于图17的显示,为什么是这个样子的呢?对于Button,其父view默认setClipChildren(true),所以画布会根据Button的边界进行一次裁剪;而对于内部的FrameLayout,其父view设置了setClipChildren(false),所以画布并不会根据它的边界进行裁剪,所以就显示出来了。

需要注意的是,虽然Button显示完全了,但是其父view边界之外的区域不能响应点击事件。所以setClipChildren方法的注释是这样写的:

默认情况下,子view在绘制之前会根据它的边界进行裁剪。ViewGroup可以覆写该方法以作动画之用。

我的理解是,看看就得了,别摸!!!

2 android:clipToPadding

若该属性为true,并且设置了padding,则ViewGroup会添加一个CLIP_TO_PADDING_MASK的标志位。该标志位会影响

protected boolean drawChild(Canvas canvas, View child, long drawingTime) {

return child.draw(canvas, this, drawingTime);

}

方法中的cancas,如下:

ViewGroup#dispatchDraw

final boolean clipToPadding = (flags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK;

if (clipToPadding) {

clipSaveCount = canvas.save(Canvas.CLIP_SAVE_FLAG);

canvas.clipRect(mScrollX + mPaddingLeft, mScrollY + mPaddingTop,

mScrollX + mRight - mLeft - mPaddingRight,

mScrollY + mBottom - mTop - mPaddingBottom);

}

对画布进行裁剪,留出padding的余量。

该属性一般用在可滚动的view上,如ScrollView,ListView,GridView,RecyclerView等。

对如下布局:

android:id="@+id/scroll"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#ffc"

android:padding="30dp"

android:visibility="visible">

android:id="@+id/layout1"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="vertical">

android:id="@+id/emotion1"

android:layout_width="match_parent"

android:layout_height="900dp"

android:background="#9c9"

android:text="一乡二里共三夫子不识四书五经六艺竟敢教七八九子十分大胆,十室九贫凑得八两七钱六分五毫四厘尚且三心二意一等下流"

android:textSize="19dp"

android:tooltipText="sssssssssssssss" />

显示效果为:

04df7e736fa4

图18

为ScrollView添加android:clipToPadding="false"后:

04df7e736fa4

图19

可以看到,在overscroll时,两段阴影部分的位置也变了。

3 动画相关

android:layoutAnimation、android:animateLayoutChanges

参考android 动画系列 (3) - layoutAnimation 视图动画,说的很详细。

4 android:splitMotionEvents

对应的方法如下:

public void setMotionEventSplittingEnabled(boolean split) {

// TODO Applications really shouldn't change this setting mid-touch event,

// but perhaps this should handle that case and send ACTION_CANCELs to any child views

// with gestures in progress when this is changed.

if (split) {

mGroupFlags |= FLAG_SPLIT_MOTION_EVENTS;

} else {

mGroupFlags &= ~FLAG_SPLIT_MOTION_EVENTS;

}

}

true: 父类将多点触控分配给对应的view

false: 父类将多点触控分配给第一个获得触摸事件的view

该属性默认是true。如下:

public ViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {

super(context, attrs, defStyleAttr, defStyleRes);

initViewGroup();

//该方法设置了的属性才会有默认值。对于XML文件没有设置的属性,不用理会该方法中的默认值。

initFromAttributes(context, attrs, defStyleAttr, defStyleRes);

}

private void initViewGroup() {

....

if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {

mGroupFlags |= FLAG_SPLIT_MOTION_EVENTS;

...

}

默认情况下:

04df7e736fa4

图20

可以看到,两个ScrollView可以独立滑动。设置android:splitMotionEvents="false"

04df7e736fa4

图21

可以看到,只能滑动一个ScrollView,该ScrollView是先获得Down事件的那个。

至此,View和ViewGroup除focus相关,其他属性基本都学习了。

ScrollView

1 android:fillViewport

设置ScrollView是否对内容进行拉伸,来适配ScrollView的高度,默认false。对应方法如下:

public void setFillViewport(boolean fillViewport) {

if (fillViewport != mFillViewport) {

mFillViewport = fillViewport;

requestLayout();

}

}

看如下布局:

android:id="@+id/scroll"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:fillViewport="false"

android:overScrollMode="ifContentScrolls">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="#9c9"

android:gravity="center"

android:text="TextView"

android:textSize="19dp" />

04df7e736fa4

屏幕快照 2019-11-02 上午11.34.28.png

修改android:fillViewport="true":

04df7e736fa4

屏幕快照 2019-11-02 上午11.38.02.png

ImageView

关于ScaleType比较基础,这里不再多说了。

1 android:adjustViewBounds

使View的尺寸和Drawable保持同样的宽高比。对应的方法为:

public void setAdjustViewBounds(boolean adjustViewBounds) {

mAdjustViewBounds = adjustViewBounds;

if (adjustViewBounds) {

setScaleType(ScaleType.FIT_CENTER);

}

}

可以看到,该属性会设置ScaleType为FIT_CENTER,这样可以保证Drawable刚好填满View。该属性对应的成员变量为mAdjustViewBounds。

不过ImageView解析XML属性的顺序如下:

setAdjustViewBounds(a.getBoolean(R.styleable.ImageView_adjustViewBounds, false));

...

final int index = a.getInt(R.styleable.ImageView_scaleType, -1);

if (index >= 0) {

setScaleType(sScaleTypeArray[index]);

}

所以如果XML同样设置了ScaleType,则以开发者设置的为准。

mAdjustViewBounds在onMeasure时会影响View的尺寸。

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

...

int w;

int h;

...

// We are allowed to change the view's width

boolean resizeWidth = false;

// We are allowed to change the view's height

boolean resizeHeight = false;

final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);

final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);

...

w = mDrawableWidth;

h = mDrawableHeight;

...

//检查是否设置了mAdjustViewBounds

if (mAdjustViewBounds) {

//只有在任意一边没有设置固定尺寸的情况下才可以resize

resizeWidth = widthSpecMode != MeasureSpec.EXACTLY;

resizeHeight = heightSpecMode != MeasureSpec.EXACTLY;

desiredAspect = (float) w / (float) h;

}

...

if (resizeWidth || resizeHeight) {

//根据宽度重新计算高度,或者根据高度重新计算宽度

...

} else {

...

}

setMeasuredDimension(widthSize, heightSize);

}

这里要注意的是,ImageView的宽高至少有一边是wrapContent,mAdjustViewBounds才能生效。并且View的尺寸只是和Drawable的尺寸保持宽高比一致,并不是大小一致。通常Drawable还是要被缩放。同时,因为ImageView设置Drawable的方法都要调用requestLayout(),所以ImageView的尺寸会动态调整。

2 android:drawableAlpha

不同于View的属性android:alpha,android:drawableAlpha用来设置Drawable的透明度。对应的方法为:

public void setImageAlpha(int alpha) {

setAlpha(alpha);

}

@Deprecated

public void setAlpha(int alpha) {

alpha &= 0xFF; // keep it legal

if (mAlpha != alpha) {

mAlpha = alpha;

mColorMod = true;

applyColorMod();

invalidate();

}

}

取值范围0~255。View的setAlpha:

public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {

ensureTransformationInfo();

if (mTransformationInfo.mAlpha != alpha) {

setAlphaInternal(alpha);

if (onSetAlpha((int) (alpha * 255))) {

mPrivateFlags |= PFLAG_ALPHA_SET;

// subclass is handling alpha - don't optimize rendering cache invalidation

invalidateParentCaches();

invalidate(true);

} else {

mPrivateFlags &= ~PFLAG_ALPHA_SET;

invalidateViewProperty(true, false);

mRenderNode.setAlpha(getFinalAlpha());

}

}

}

用来设置整个View的透明度,取值范围0~1。

例子如下:

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#9c9"

android:orientation="vertical">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="#c99"

android:src="@drawable/sss" />

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:alpha="0.5"

android:background="#c99"

android:src="@drawable/sss" />

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="#c99"

android:src="@drawable/sss"

tools:drawableAlpha="128"/>

04df7e736fa4

图22

注:虽然ImageView有android:drawableAlpha属性,但直接在XML中设置,编译时会报错,提示attribute android:drawableAlpha is private。所以上例使用了tools命名空间,截图是预览页面。

虽然XML中不能设置该属性,但我们可以通过java代码调用setImageAlpha方法进行设置。不清楚google为什么这么搞,好奇怪,难道是bug?

3 android:cropToPadding

public void setCropToPadding(boolean cropToPadding) {

if (mCropToPadding != cropToPadding) {

mCropToPadding = cropToPadding;

requestLayout();

invalidate();

}

}

该属性与ViewGroup的android:clipToPadding功能类似。在ImageView#onDraw方法中:

if (mCropToPadding) {

final int scrollX = mScrollX;

final int scrollY = mScrollY;

canvas.clipRect(scrollX + mPaddingLeft, scrollY + mPaddingTop,

scrollX + mRight - mLeft - mPaddingRight,

scrollY + mBottom - mTop - mPaddingBottom);

}

canvas.translate(mPaddingLeft, mPaddingTop);

if (mDrawMatrix != null) {

canvas.concat(mDrawMatrix);

}

mDrawable.draw(canvas);

同样是裁剪画布的操作。

对如下两个ImageView:

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="#c9c"

android:padding="20dp"

android:scrollY="100dp"

android:src="@drawable/sss" />

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="#999"

android:cropToPadding="true"

android:padding="20dp"

android:scrollY="100dp"

android:src="@drawable/sss" />

显示效果为:

04df7e736fa4

图23

TextView

1 android:editable

该属性决定TextView是否可编辑,默认值为false,由以下方法获得:

protected boolean getDefaultEditable() {

return false;

}

EditText就是覆写该方法,返回了true。

若可编辑,则会创建Editor,以接收处理各种KeyEvent。

如下例子:

android:id="@+id/text"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:editable="true"

android:focusable="true"

android:focusableInTouchMode="true"

android:text="一乡二里共三夫子不识四书五经六艺竟敢教七八九子十分大胆,十室九贫凑得八两七钱六分五毫四厘尚且三心二意一等下流"

android:textSize="19dp" />

04df7e736fa4

图24

需要注意的是,这里必须设置android:focusable="true"和android:focusableInTouchMode="true",否则TextView无法获取焦点。

2 限制输入的字符类型

3 android:selectAllOnFocus

默认false,对应方法:

@android.view.RemotableViewMethod

public void setSelectAllOnFocus(boolean selectAllOnFocus) {

createEditorIfNeeded();

mEditor.mSelectAllOnFocus = selectAllOnFocus;

if (selectAllOnFocus && !(mText instanceof Spannable)) {

setText(mText, BufferType.SPANNABLE);

}

}

以EditText为例,设置为true,在获取焦点时,会选中全部内容

4 链接

android:autoLink设置是否将电话、邮箱、网址等显示为链接形式。默认都不显示为链接形式。

android:linksClickable设置链接是否可点击。默认true

5 尺寸相关

android:ems

控制TextView的宽度,只在android:layout_width="wrap_content"时有效。ems表示字符的宽度,可粗略理解为1ems相当于1个汉字的宽度。英文的非等宽字体每个字符宽度不同,所以1ems所能容下的数量也不同。

android:lines android:height

控制TextView的高度,只在android:layout_height="wrap_content"时有效。并且两个属性互斥,看源码:

public void setLines(int lines) {

mMaximum = mMinimum = lines;

mMaxMode = mMinMode = LINES;

requestLayout();

invalidate();

}

public void setHeight(int pixels) {

mMaximum = mMinimum = pixels;

mMaxMode = mMinMode = PIXELS;

requestLayout();

invalidate();

}

此外还有单独的android:maxEms等属性设置。

以上属性影响的是TextView的尺寸,与内容无关,注意与android:maxLength区分开。android:maxLength控制显示的最大字符数,实现如下:

if (maxlength >= 0) {

setFilters(new InputFilter[] { new InputFilter.LengthFilter(maxlength) });

} else {

setFilters(NO_FILTERS);

}

通过LengthFilter控制最大字符数。

6 android:includeFontPadding

默认是true。设置为false,可以一定程度去掉上下的留白。注意,和设置padding属性是毫无关系的。

7 android:cursorVisible

设置是否隐藏掉光标。

8 android:textScaleX

设置横向拉伸/压缩内容

9 android:freezesText

该属性决定TextView被意外销毁时,是否保存当前内容。对应的java方法:

public void setFreezesText(boolean freezesText) {

mFreezesText = freezesText;

}

public boolean getFreezesText() {

return mFreezesText;

}

看源码是如何起作用的:

@Override

public Parcelable onSaveInstanceState() {

Parcelable superState = super.onSaveInstanceState();

// Save state if we are forced to

final boolean freezesText = getFreezesText();

...

SavedState ss = new SavedState(superState);

if (freezesText) {

if (mText instanceof Spanned) {

final Spannable sp = new SpannableStringBuilder(mText);

if (mEditor != null) {

removeMisspelledSpans(sp);

sp.removeSpan(mEditor.mSuggestionRangeSpan);

}

ss.text = sp;

} else {

ss.text = mText.toString();

}

}

...

return superState;

}

可以看到设置freezesText后,在onSaveInstanceState时就可以保存当前内容。

需要注意的是,想要保存内容,还需要设置当前视图树唯一的id,原因见View源码——saveInstanceState

EditText覆写了get方法:

@Override

public boolean getFreezesText() {

return true;

}

所以在有唯一id的情况下,默认会正确保存当前内容。

10 cursor|handle相关

android:id="@+id/editText"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginTop="10dp"

android:text="一乡二里共三夫子,不识四书五经六义,竟敢教七八九子,十分大胆"

android:textSelectHandleLeft="@drawable/cursor_red"

android:textSelectHandleRight="@drawable/cursor_green"

android:textSelectHandle="@drawable/cursor_blue"

android:textCursorDrawable="@drawable/cursor_purple"

android:textSize="19dp" />

04df7e736fa4

光标和handle

04df7e736fa4

handleLeft和handleRight

除光标外,其他三个设置在MIUI上无效

11 android:textIsSelectable

设置文本是否可被选中,选中态会弹出上下文菜单,默认false。如:

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="鸡叫一声撅一撅,\n鸡叫两声撅两撅。\n三声唤出扶桑日,\n扫败残星与晓月。"

android:textColor="#000"

android:textIsSelectable="true"

android:textSize="20dp" />

04df7e736fa4

device-2019-11-01-151930.png

该菜单可以通过长按或者双击唤出。

12 文字上下边距

除了可以设置padding,还有两个方法:

android:firstBaselineToTopHeight="30dp"

android:lastBaselineToBottomHeight="30dp"

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值