View源碼——android:XX屬性

基于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:

圖1 原圖

設置android:scrollX=-50dp贞瞒,背景不移動偶房,內(nèi)容右移:

圖2 android:scrollX=-50dp

至于為什么不影響背景,后續(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"

顯示如下:

圖3 matrix變換

藍色方框是matrix變換之前的位置。
為當前View設置點擊事件乒融,可以發(fā)現(xiàn)掰盘,僅在點擊View的繪制區(qū)域(非白色區(qū)域)時觸發(fā)onClick方法,在點擊藍色方框內(nèi)的空白區(qū)域時不會觸發(fā)赞季。
有以下結論:

  1. matrix變換影響整個View的顯示(包括子View)
  2. matrix與scrollX srollY互不影響
  3. 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是這個樣子的:

圖4

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">
圖5

scrollview的背景是米黃色征椒。可以看到湃累,在可以滑動的邊上勃救,呈現(xiàn)出淡出的效果。

2治力、android:scrollbarSize控制滾動條的尺寸蒙秒。
android:scrollbarStyle控制滾動條的風格。有四個值:insideOverlay,insideInset,outsideOverlay,outsideInset宵统。
為了方便區(qū)分這四個風格晕讲,我們?yōu)镾crollView設置一個30dp的padding, 同時scrollbarSize設置為30dp。四種風格如下:

圖6 insideOverlay
圖7 insideInset
圖8 outsideOverlay
圖9 outsideInset

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欧瘪。如下:

圖10

透明黑色的部分是蓋的新的window,由圖可知匙赞,按鈕被window遮擋的部分也可以響應點擊事件佛掖。
現(xiàn)在我們給根布局LinearLayout(按鈕本身或包含它的布局都可以)加上android:filterTouchesWhenObscured="true"

圖11

從圖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" />
圖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的方法关贵,可以根據(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()));
            }
        });
圖13

需要注意的是卖毁,這里只影響顯示的內(nèi)容揖曾,不影響點擊區(qū)域落萎。
同時,也不是任意的outline形狀都支持裁剪炭剪。只有矩形练链、圓角矩形、圓形這三種支持奴拦。其他形狀媒鼓,包括橢圓都不支持。Outline類的方法canClip()可獲取當前outline是否支持裁剪错妖。其他設置方法可查看Outline類源碼绿鸣。

11 android:tooltipText

api26新加。給view設置一個功能提示暂氯。與電腦軟件中潮模,鼠標停留在一個按鈕上,會彈出一個功能說明一樣株旷。這里通過長按觸發(fā)再登。
如下面的TextView:

圖14

12 android:keyboardNavigationCluster

api26新增

google鏈接

圖15

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ā)者模式的布局邊界開關梯嗽,顯示如下:

圖16

在外層的FrameLayout上加上android:clipChildren="false"齿尽,顯示如下:

圖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在繪制時,也會自行調(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>

顯示效果為:

圖18

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

圖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;
        ...
    }

默認情況下:

圖20

可以看到荣堰,兩個ScrollView可以獨立滑動。設置android:splitMotionEvents="false"

圖21

可以看到竭翠,只能滑動一個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>
屏幕快照 2019-11-02 上午11.34.28.png

修改android:fillViewport="true"

屏幕快照 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忧饭,則以開發(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:alphaandroid: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>
圖22

注:雖然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" />

顯示效果為:

圖23

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" />
圖24

需要注意的是七问,這里必須設置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" />
光標和handle
handleLeft和handleRight

除光標外,其他三個設置在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" />
device-2019-11-01-151930.png

該菜單可以通過長按或者雙擊喚出淹仑。

12 文字上下邊距

除了可以設置padding,還有兩個方法:

        android:firstBaselineToTopHeight="30dp"
        android:lastBaselineToBottomHeight="30dp"

參考Android 9.0關于字體的新特性


最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末肺孵,一起剝皮案震驚了整個濱河市匀借,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌平窘,老刑警劉巖怀吻,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異初婆,居然都是意外死亡,警方通過查閱死者的電腦和手機猿棉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門磅叛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人萨赁,你說我怎么就攤上這事弊琴。” “怎么了杖爽?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵敲董,是天一觀的道長紫皇。 經(jīng)常有香客問我,道長腋寨,這世上最難降的妖魔是什么聪铺? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮萄窜,結果婚禮上铃剔,老公的妹妹穿的比我還像新娘。我一直安慰自己查刻,他們只是感情好键兜,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著穗泵,像睡著了一般普气。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上佃延,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天现诀,我揣著相機與錄音,去河邊找鬼苇侵。 笑死赶盔,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的榆浓。 我是一名探鬼主播于未,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼陡鹃!你這毒婦竟也來了烘浦?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤萍鲸,失蹤者是張志新(化名)和其女友劉穎闷叉,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體脊阴,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡握侧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了嘿期。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片品擎。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖备徐,靈堂內(nèi)的尸體忽然破棺而出萄传,到底是詐尸還是另有隱情,我是刑警寧澤蜜猾,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布秀菱,位于F島的核電站振诬,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏衍菱。R本人自食惡果不足惜赶么,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望梦碗。 院中可真熱鬧禽绪,春花似錦、人聲如沸洪规。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽斩例。三九已至雄人,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間念赶,已是汗流浹背础钠。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留叉谜,地道東北人旗吁。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像停局,于是被迫代替她去往敵國和親很钓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359