/** * 为每个View设置AccessibilityDelegate,监听各种事件 */public class AutoTrackActivity extends AppCompatActivity { @Override public Object getSystemService(@NonNull String name) { Object object = super.getSystemService(name); if (traceEnable() && object instanceof LayoutInflater) { return new TrackLayoutInflater((LayoutInflater) object, this); } return object; } public boolean traceEnable() { return true; } public static class TrackLayoutInflater extends LayoutInflater { private final LayoutInflater mProxy; public TrackLayoutInflater(LayoutInflater proxy, Context context) { super(proxy, context); this.mProxy = proxy; } @Override public LayoutInflater cloneInContext(Context newContext) { return new TrackLayoutInflater(mProxy, newContext); } @Override public View inflate(int resource, @Nullable ViewGroup root) { View view = mProxy.inflate(resource, root); View content = view.findViewById(android.R.id.content); if (content instanceof ViewGroup) { flatViews((ViewGroup) content); } return view; } private static void bindAccessibilityDelegate(View view) { if (view != null) { view.setAccessibilityDelegate(AccessibilityDelegateWrapper.create(view, new View.AccessibilityDelegate() { @Override public void sendAccessibilityEvent(View host, int eventType) { if (eventType == AccessibilityEvent.TYPE_VIEW_CLICKED) { Log.i("csz", host.getClass().getCanonicalName() + " click"); }else if (eventType == AccessibilityEvent.TYPE_VIEW_LONG_CLICKED){ Log.i("csz", host.getClass().getCanonicalName() + " longClick"); } super.sendAccessibilityEvent(host, eventType); } })); } } private void flatViews(ViewGroup group) { for (int i = 0; i < group.getChildCount(); i++) { View child = group.getChildAt(i); bindAccessibilityDelegate(child); if (child instanceof ViewGroup){ flatViews((ViewGroup) child); } } } }}
static class SavedState extends BaseSavedState { float progress; SavedState(Parcelable superState) { super(superState); } private SavedState(Parcel in) { super(in); progress = (Float) in.readFloat(); } @Override public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); out.writeValue(progress); } @Override public String toString() { return " p =" + progress + "}"; } public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { @Override public SavedState createFromParcel(Parcel in) { return new SavedState(in); } @Override public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Override public Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.progress = mProgress; return ss; } @Override public void onRestoreInstanceState(Parcelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setProgress(ss.progress); requestLayout(); }
private void drag() { btn.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); View.DragShadowBuilder builder = new View.DragShadowBuilder(v); ClipData data = ClipData.newPlainText("label", "我是文本内容!"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { v.startDragAndDrop(data, builder, v, 0); } else { v.startDrag(data, builder, v, 0); } return true; } }); frame.setOnDragListener(new View.OnDragListener() { @Override public boolean onDrag(View v, DragEvent event) { //获取事件 int action = event.getAction(); switch (action) { case DragEvent.ACTION_DRAG_STARTED: btn.setVisibility(View.INVISIBLE); Log.d("csz", "开始拖拽"); break; case DragEvent.ACTION_DRAG_ENDED: Log.d("csz", "结束拖拽"); break; case DragEvent.ACTION_DRAG_ENTERED: Log.d("csz", "拖拽的view进入监听的view时"); break; case DragEvent.ACTION_DRAG_EXITED: Log.d("csz", "拖拽的view离开监听的view时"); frame.setBackgroundColor(Color.BLUE); break; case DragEvent.ACTION_DRAG_LOCATION: float x = event.getX(); float y = event.getY(); frame.setBackgroundColor(Color.RED); Log.i("csz", "拖拽的view在监听view中的位置:x =" + x + ",y=" + y); break; case DragEvent.ACTION_DROP: Log.i("csz", "释放拖拽的view"); if( event.getLocalState() != null){ View localState = (View) event.getLocalState(); FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); ((ViewGroup) localState.getParent()).removeView(localState); frame.addView(localState, layoutParams); btn.setVisibility(View.VISIBLE); } break; } return true; } }); }
4.OnApplyWindowInsetsListener处理WindowInsets
root.setSystemUiVisibility(root.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); final int paddingTop = root.getPaddingTop(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { root.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() { @Override public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) { root.setPadding(root.getPaddingLeft(), paddingTop + insets.getSystemWindowInsetTop(), root.getPaddingRight(), root.getPaddingBottom()); return insets; } }); //这不是绝对必要的,但确实可以解决WindowInsets的分派方式 if (root.isAttachedToWindow()) { root.requestApplyInsets(); } else { root.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(View v) { v.removeOnAttachStateChangeListener(this); v.requestApplyInsets(); } @Override public void onViewDetachedFromWindow(View v) { } }); } }
5.getGlobalVisibleRect(rect,null) 获取在根视图上的位置
6.getHitRect(rect) 获取在父视图上的位置(left,top,right,bottom)
7.设置触控和声音反馈
btn.setHapticFeedbackEnabled(true);btn.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);btn.playSoundEffect(SoundEffectConstants.CLICK);
8.setActivated(true) 激活视图,例如Toolbar激活后会有阴影效果
10.setClipBounds对视图裁剪,不会影响原有宽高
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { btn.setClipBounds(new Rect(0,0,btn.getWidth()/2,btn.getHeight()/2)); }
11.StateListAnimator为view的state状态改变加动画
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { StateListAnimator stateListAnimator = new StateListAnimator(); ObjectAnimator animator = ObjectAnimator.ofFloat(iv, "alpha", 0.5f, 1.f).setDuration(500); ObjectAnimator reverseAnimator = animator.clone(); reverseAnimator.setFloatValues(1.f, 0.5f); stateListAnimator.addState(new int[]{android.R.attr.state_selected}, animator); stateListAnimator.addState(new int[]{-android.R.attr.state_selected}, reverseAnimator); iv.setStateListAnimator(stateListAnimator); iv.setSelected(lefted = !lefted);}
12.ColorStateList为view的state状态改变颜色,或者TextView的字体颜色
ColorStateList stateList = new ColorStateList(new int[][]{{android.R.attr.state_selected, android.R.attr.state_checked}, {-android.R.attr.state_selected, -android.R.attr.state_checked}}, new int[]{Color.BLUE, Color.RED}); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { ColorStateListDrawable drawable = new ColorStateListDrawable(stateList); iv.setBackground(drawable); }
下面对ViewGroup的拓展使用进行说明:
2.updateViewLayout 更新child的LayoutParams