基于api28
常用屬性不再贅述叠洗,只看一些不常用的或者新添加的屬性胰蝠。
1 padding
android:paddingHorizontal //同時設置左右padding
android:paddingVertical //同時設置上下padding
以上屬性api26添加违霞。
2 scroll
android:scrollX
android:scrollY
以上兩個屬性對應的成員變量為mScrollX mScrollX
,在繪制之前弹谁,會執(zhí)行
canvas.translate(-mScrollX, -mScrollY);
同時影響當前View的繪制乾巧,及其children的繪制。但對當前view的背景沒有影響预愤!
偏移量 > 0沟于, 內(nèi)容向右下偏移;
偏移量 < 0植康, 內(nèi)容向左上偏移旷太。
注:在xml中設置View的繼承類的
android:scrollX、android:scrollY
不一定起作用销睁,依賴于具體的實現(xiàn)供璧。
比如ScrollView,由于在滾動時會判斷getChildCount() > 0
榄攀,而初始化時還沒有子View嗜傅,所以不起作用。
如下圖為自定義的View檩赢,背景為黑色吕嘀,在onDraw方法中畫了一個圓,寬高均為100dp:
設置android:scrollX=-50dp
贞瞒,背景不移動偶房,內(nèi)容右移:
至于為什么不影響背景,后續(xù)再學習军浆。
3 matrix變換
<!-- 設置scale棕洋、rotation變換的中心點 -->
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"
顯示如下:
藍色方框是matrix變換之前的位置。
為當前View設置點擊事件乒融,可以發(fā)現(xiàn)掰盘,僅在點擊View的繪制區(qū)域(非白色區(qū)域)時觸發(fā)onClick方法,在點擊藍色方框內(nèi)的空白區(qū)域時不會觸發(fā)赞季。
有以下結論:
- matrix變換影響整個View的顯示(包括子View)
- matrix與scrollX srollY互不影響
- matrix會影響可點擊區(qū)域
有的同學還知道有個android:elevation
屬性愧捕,它和android:translationZ
有什么區(qū)別呢?
android系統(tǒng)中申钩,View所在的坐標系是一個三維的次绘,View最終的坐標可以通過getX getY getZ
三個方法得到。看一下這三個方法的實現(xiàn):
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
默認false豁跑。詳細分析見 View源碼——fitSystemWindows詳解
5 saveEnabled
android:saveEnabled
設置View是否意外銷毀時,會調(diào)用onSaveInstanceState方法來保存狀態(tài)命迈。默認為true贩绕。詳見View源碼——saveInstanceState
6 duplicateParentState
設置當前view是否使用父view的狀態(tài),默認false壶愤。該狀態(tài)主要影響drawable的顯示。View源碼——duplicateParentState
7 滾動相關
以如下布局為例:
<ScrollView
android:id="@+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffc">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
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" />
</LinearLayout>
</ScrollView>
此時的ui是這個樣子的:
1馏鹤、ScrollView添加兩個屬性:
<ScrollView
android:id="@+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fadingEdgeLength="50dp"
android:requiresFadingEdge="vertical"
android:background="#ffc">
scrollview的背景是米黃色征椒。可以看到湃累,在可以滑動的邊上勃救,呈現(xiàn)出淡出的效果。
2治力、android:scrollbarSize
控制滾動條的尺寸蒙秒。
android:scrollbarStyle
控制滾動條的風格。有四個值:insideOverlay,insideInset,outsideOverlay,outsideInset
宵统。
為了方便區(qū)分這四個風格晕讲,我們?yōu)镾crollView設置一個30dp的padding, 同時scrollbarSize設置為30dp。四種風格如下:
3马澈、android:overScrollMode
控制scrollView滑到頭時瓢省,是否顯示陰影。圖4可以很明顯看出來滑到頭時的陰影部分痊班。有三個取值:
- never: 從不顯示
- always:滑到頭時顯示
- ifContentScrolls(默認):若內(nèi)容過短勤婚,scrollView無法滑動,則不顯示涤伐;否則顯示馒胆。
4、android:isScrollContainer
與軟鍵盤有關凝果。參考android:isScrollContainer 屬性的作用
5祝迂、android:verticalScrollbarPosition
垂直滾動條的顯示位置,有三個值:left right defaultPosition
豆村,很簡單不再多說液兽。
8 android:filterTouchesWhenObscured
view被其他窗口遮擋時,是否過濾觸摸事件。默認false四啰。只看說明很難理解宁玫,下面看一個例子。
布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:gravity="center_horizontal"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/bt1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="toast"
android:textAllCaps="false" />
</FrameLayout>
</LinearLayout>
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欧瘪。如下:
透明黑色的部分是蓋的新的window,由圖可知匙赞,按鈕被window遮擋的部分也可以響應點擊事件佛掖。
現(xiàn)在我們給根布局LinearLayout(按鈕本身或包含它的布局都可以)加上android:filterTouchesWhenObscured="true"
從圖11可以看到,按鈕被遮擋的部分涌庭,已經(jīng)不再響應點擊事件了芥被。
9 android:stateListAnimator
關于這個屬性的講解有很多,不再贅述
10 outline相關
api21開始才有的坐榆。api21之后拴魄,view添加elevation、transitionZ的方法席镀,由二維空間變成了三維空間匹中。在Z軸上,可以通過outline來為view設置陰影等豪诲。
xml文件可以設置以下三個屬性:
android:outlineAmbientShadowColor
android:outlineSpotShadowColor
android:outlineProvider
第一個用來設置環(huán)境光顏色顶捷,不過肉眼難以分辨。默認黑色屎篱。
第二個用來設置陰影的主題顏色服赎。默認黑色。
第三個設置outline的獲取方式芳室,分別為:background(默認)专肪、none、bounds堪侯、paddedBounds
嚎尤。區(qū)別下面會講。
先看個例子:
xml
<ImageView
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" />
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
的方法关贵,可以根據(jù)outline裁剪內(nèi)容
對上面的例子,在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()));
}
});
需要注意的是卖毁,這里只影響顯示的內(nèi)容揖曾,不影響點擊區(qū)域落萎。
同時,也不是任意的outline形狀都支持裁剪炭剪。只有矩形练链、圓角矩形、圓形這三種支持奴拦。其他形狀媒鼓,包括橢圓都不支持。Outline類的方法canClip()
可獲取當前outline是否支持裁剪错妖。其他設置方法可查看Outline類源碼绿鸣。
11 android:tooltipText
api26新加。給view設置一個功能提示暂氯。與電腦軟件中潮模,鼠標停留在一個按鈕上,會彈出一個功能說明一樣株旷。這里通過長按觸發(fā)再登。
如下面的TextView:
12 android:keyboardNavigationCluster
api26新增
13自動填充
api26新增的自動填充功能,目前使用很少晾剖,不再介紹。
沒搞明白的幾個
android:scrollIndicators
ViewGroup的屬性
1 android:clipChildren
該屬性默認是true
看這樣一個布局:
<FrameLayout
android:id="@+id/btLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
android:layout_width="100dp"
android:layout_height="100dp">
<Button
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" />
</FrameLayout>
</FrameLayout>
打開開發(fā)者模式的布局邊界開關梯嗽,顯示如下:
在外層的FrameLayout上加上android:clipChildren="false"
齿尽,顯示如下:
該屬性對應的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在繪制時,也會自行調(diào)用setClipToBounds方法
}
invalidate(true);
}
}
該方法只會影響直接子view灯节。最終調(diào)用的是RenderNode的setClipToBounds
方法循头。setClipToBounds
方法會根據(jù)view的邊界對顯示區(qū)域進行裁剪。
RenderNode后續(xù)再講炎疆。感興趣的同學也可以查詢其他資料卡骂。也可以把它暫時看做是canvas。
上例中形入,圖16的顯示應該不必說了全跨。關于圖17的顯示,為什么是這個樣子的呢亿遂?對于Button浓若,其父view默認setClipChildren(true)
,所以畫布會根據(jù)Button的邊界進行一次裁剪蛇数;而對于內(nèi)部的FrameLayout挪钓,其父view設置了setClipChildren(false)
,所以畫布并不會根據(jù)它的邊界進行裁剪耳舅,所以就顯示出來了碌上。
需要注意的是,雖然Button顯示完全了,但是其父view邊界之外的區(qū)域不能響應點擊事件馏予。所以setClipChildren
方法的注釋是這樣寫的:
默認情況下天梧,子view在繪制之前會根據(jù)它的邊界進行裁剪。ViewGroup可以覆寫該方法以作動畫之用吗蚌。
我的理解是臀突,看看就得了,別摸@鬯獭L紊帷!
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等翘悉。
對如下布局:
<ScrollView
android:id="@+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffc"
android:padding="30dp"
android:visibility="visible">
<LinearLayout
android:id="@+id/layout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/emotion1"
android:layout_width="match_parent"
android:layout_height="900dp"
android:background="#9c9"
android:text="一鄉(xiāng)二里共三夫子不識四書五經(jīng)六藝竟敢教七八九子十分大膽,十室九貧湊得八兩七錢六分五毫四厘尚且三心二意一等下流"
android:textSize="19dp"
android:tooltipText="sssssssssssssss" />
</LinearLayout>
</ScrollView>
顯示效果為:
為ScrollView添加android:clipToPadding="false"
后:
可以看到居触,在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;
...
}
默認情況下:
可以看到荣堰,兩個ScrollView可以獨立滑動。設置android:splitMotionEvents="false"
可以看到竭翠,只能滑動一個ScrollView振坚,該ScrollView是先獲得Down事件的那個。
至此斋扰,View和ViewGroup除focus相關渡八,其他屬性基本都學習了啃洋。
ScrollView
1 android:fillViewport
設置ScrollView是否對內(nèi)容進行拉伸,來適配ScrollView的高度屎鳍,默認false宏娄。對應方法如下:
public void setFillViewport(boolean fillViewport) {
if (fillViewport != mFillViewport) {
mFillViewport = fillViewport;
requestLayout();
}
}
看如下布局:
<ScrollView
android:id="@+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="false"
android:overScrollMode="ifContentScrolls">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#9c9"
android:gravity="center"
android:text="TextView"
android:textSize="19dp" />
</ScrollView>
修改android:fillViewport="true"
:
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忧饭,則以開發(fā)者設置的為準扛伍。
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) {
//根據(jù)寬度重新計算高度词裤,或者根據(jù)高度重新計算寬度
...
} else {
...
}
setMeasuredDimension(widthSize, heightSize);
}
這里要注意的是刺洒,ImageView的寬高至少有一邊是wrapContent,mAdjustViewBounds
才能生效吼砂。并且View的尺寸只是和Drawable的尺寸保持寬高比一致逆航,并不是大小一致。通常Drawable還是要被縮放渔肩。同時纸泡,因為ImageView設置Drawable的方法都要調(diào)用requestLayout()
,所以ImageView的尺寸會動態(tài)調(diào)整赖瞒。
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磷仰。
例子如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#9c9"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#c99"
android:src="@drawable/sss" />
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.5"
android:background="#c99"
android:src="@drawable/sss" />
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#c99"
android:src="@drawable/sss"
tools:drawableAlpha="128"/>
</LinearLayout>
注:雖然ImageView有
android:drawableAlpha
屬性袍嬉,但直接在XML中設置,編譯時會報錯灶平,提示attribute android:drawableAlpha is private
伺通。所以上例使用了tools命名空間,截圖是預覽頁面逢享。
雖然XML中不能設置該屬性罐监,但我們可以通過java代碼調(diào)用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:
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#c9c"
android:padding="20dp"
android:scrollY="100dp"
android:src="@drawable/sss" />
<ImageView
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" />
顯示效果為:
TextView
1 android:editable
該屬性決定TextView是否可編輯航罗,默認值為false,由以下方法獲得:
protected boolean getDefaultEditable() {
return false;
}
EditText就是覆寫該方法屁药,返回了true粥血。
若可編輯,則會創(chuàng)建Editor
酿箭,以接收處理各種KeyEvent复亏。
如下例子:
<TextView
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="一鄉(xiāng)二里共三夫子不識四書五經(jīng)六藝竟敢教七八九子十分大膽,十室九貧湊得八兩七錢六分五毫四厘尚且三心二意一等下流"
android:textSize="19dp" />
需要注意的是七问,這里必須設置android:focusable="true"
和android:focusableInTouchMode="true"
蜓耻,否則TextView無法獲取焦點。
2 限制輸入的字符類型
參考Android EditText限制輸入字符的5種實現(xiàn)方式
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,在獲取焦點時讥耗,會選中全部內(nèi)容
4 鏈接
android:autoLink
設置是否將電話有勾、郵箱、網(wǎng)址等顯示為鏈接形式古程。默認都不顯示為鏈接形式蔼卡。
android:linksClickable
設置鏈接是否可點擊。默認true
5 尺寸相關
android:ems
控制TextView的寬度挣磨,只在android:layout_width="wrap_content"
時有效雇逞。ems表示字符的寬度,可粗略理解為1ems相當于1個漢字的寬度茁裙。英文的非等寬字體每個字符寬度不同塘砸,所以1ems所能容下的數(shù)量也不同。
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的尺寸女轿,與內(nèi)容無關,注意與android:maxLength
區(qū)分開壕翩。android:maxLength
控制顯示的最大字符數(shù)蛉迹,實現(xiàn)如下:
if (maxlength >= 0) {
setFilters(new InputFilter[] { new InputFilter.LengthFilter(maxlength) });
} else {
setFilters(NO_FILTERS);
}
通過LengthFilter
控制最大字符數(shù)。
6 android:includeFontPadding
默認是true戈泼。設置為false婿禽,可以一定程度去掉上下的留白赏僧。注意,和設置padding屬性是毫無關系的扭倾。
7 android:cursorVisible
設置是否隱藏掉光標淀零。
8 android:textScaleX
設置橫向拉伸/壓縮內(nèi)容
9 android:freezesText
該屬性決定TextView被意外銷毀時,是否保存當前內(nèi)容膛壹。對應的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時就可以保存當前內(nèi)容。
需要注意的是模聋,想要保存內(nèi)容肩民,還需要設置當前視圖樹唯一的id,原因見View源碼——saveInstanceState
EditText覆寫了get方法:
@Override
public boolean getFreezesText() {
return true;
}
所以在有唯一id的情況下链方,默認會正確保存當前內(nèi)容持痰。
10 cursor|handle相關
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="一鄉(xiāng)二里共三夫子,不識四書五經(jīng)六義,竟敢教七八九子,十分大膽"
android:textSelectHandleLeft="@drawable/cursor_red"
android:textSelectHandleRight="@drawable/cursor_green"
android:textSelectHandle="@drawable/cursor_blue"
android:textCursorDrawable="@drawable/cursor_purple"<!-- 光標顏色 -->
android:textSize="19dp" />
除光標外,其他三個設置在MIUI上無效
11 android:textIsSelectable
設置文本是否可被選中祟蚀,選中態(tài)會彈出上下文菜單工窍,默認false。如:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="雞叫一聲撅一撅前酿,\n雞叫兩聲撅兩撅患雏。\n三聲喚出扶桑日,\n掃敗殘星與曉月罢维。"
android:textColor="#000"
android:textIsSelectable="true"
android:textSize="20dp" />
該菜單可以通過長按或者雙擊喚出淹仑。
12 文字上下邊距
除了可以設置padding,還有兩個方法:
android:firstBaselineToTopHeight="30dp"
android:lastBaselineToBottomHeight="30dp"