public void setErrorEnabled(boolean enabled) { if (mErrorEnabled != enabled) { if (mErrorView != null) { ViewCompat.animate(mErrorView).cancel(); } if (enabled) {//代码一 mErrorView = new TextView(getContext()); mErrorView.setTextAppearance(getContext(), mErrorTextAppearance); mErrorView.setVisibility(INVISIBLE); ViewCompat.setAccessibilityLiveRegion(mErrorView, ViewCompat.ACCESSIBILITY_LIVE_REGION_POLITE); addIndicator(mErrorView, 0); } else { mErrorShown = false; updateEditTextBackground(); removeIndicator(mErrorView);//将errorTextView从mIndicatorArea中remove 。略 mErrorView = null; } mErrorEnabled = enabled; } }从代码一中可以看出,error区域就是一个TextView,该TextView的textAppearance为mErrorTextAppearance(即errorTextAppearance对应的值),并且errorTextView是INVISIBLE。只有在调用setError()设置了error提示文字后errorTextView才可见。
private void addIndicator(TextView indicator, int index) { if (mIndicatorArea == null) { mIndicatorArea = new LinearLayout(getContext()); mIndicatorArea.setOrientation(LinearLayout.HORIZONTAL); addView(mIndicatorArea, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); // Add a flexible spacer in the middle so that the left/right views stay pinned final Space spacer = new Space(getContext()); final LinearLayout.LayoutParams spacerLp = new LinearLayout.LayoutParams(0, 0, 1f); mIndicatorArea.addView(spacer, spacerLp); if (mEditText != null) { adjustIndicatorPadding(); } } mIndicatorArea.setVisibility(View.VISIBLE); mIndicatorArea.addView(indicator, index); }从上面代码可以看出,errorTextView是被add到一个水平的线性布局中的(counterTextView也会被加到该布局中)。
<android.support.design.widget.TextInputLayout android:id="@+id/first" android:layout_width="match_parent" android:layout_height="wrap_content" app:counterEnabled="true" app:counterOverflowTextAppearance="@style/CounterOverflowApperance" app:counterTextAppearance="@style/CounterApperance" app:hintAnimationEnabled="true"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="hint" android:textColorHint="@android:color/holo_red_dark" /> </android.support.design.widget.TextInputLayout>
左边为按下效果,右边为正常时显示效果
中间的小机器人为src(继承于ImageButton,所以src属性仍旧有效)。
左图中,外围灰色的圆环的宽度为borderWidth。灰色为backgroundTint中的pressed时对应的color。中间的绿色颜色为rippleColor。
右图中,红色为backgrountTint中正常情况下的color。
在上图中,每一个按钮周围都有一圈渐变到透明的阴影。按下时阴影是通过pressedTranslationZ控制,正常时通过elevation控制。
<android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:src="@mipmap/ic_launcher" android:layout_margin="0dp" android:background="@android:color/holo_orange_dark" app:elevation="50dp" app:borderWidth="0dp" app:pressedTranslationZ="20dp" app:fabSize="normal" app:rippleColor="@android:color/holo_green_dark" app:backgroundTint="@color/fab_bg_tint" />其颜色选择器为
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@android:color/darker_gray" android:state_pressed="true" /> <item android:color="@android:color/holo_red_dark" /> </selector>从上面可以看出,ripple的颜色会覆盖掉backgrountTint中的颜色。
private static ViewGroup findSuitableParent(View view) { ViewGroup fallback = null; do { if (view instanceof CoordinatorLayout) { // 当是CoordinatorLayout时,直接返回 return (ViewGroup) view; } else if (view instanceof FrameLayout) { if (view.getId() == android.R.id.content) { // 没有找到CoordinatorLayout,但View树已经遍历到decor view了,就使用该decor view。一般情况下,该判断肯定会成功。 return (ViewGroup) view; } else { // fallback = (ViewGroup) view; } } if (view != null) { // 逆向遍历view树 final ViewParent parent = view.getParent(); view = parent instanceof View ? (View) parent : null; } } while (view != null); // If we reach here then we didn't find a CoL or a suitable content view so we'll fallback return fallback; }至于Snackbar加载的布局最终会加载到Snackbar$SnackbarLayout,SnackbarLayout是一个水平的线性布局,它里面只有一个textview(即Snackbar中的msg显示的View)与一个button(即Snackbar中action显示的View)——布局文件为design_layout_snackbar_include,里面只放了一个textview与button。
Snackbar bar = Snackbar.make(findViewById(R.id.root), "snack", Snackbar.LENGTH_SHORT) .setAction("dismiss", new View.OnClickListener() { @Override public void onClick(View v) { //snackbar中按钮的点击响应事件 } }); Snackbar.SnackbarLayout view = (Snackbar.SnackbarLayout) bar.getView(); view.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_light)); TextView msgView = (TextView) view.getChildAt(0); msgView.setTextColor(Color.WHITE); msgView.setText("msgView"); Button actionBtn = (Button) view.getChildAt(1); actionBtn.setTextColor(getResources().getColor(android.R.color.holo_red_light)); bar.show();其效果为