如何将前景属性设置为其他非FrameLayout视图

我想知道如何在不同于FrameLayout的视图中应用或模拟前景效果,如LinearLayout或RelativeLayout

这是我现在所拥有的:

<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/cardContent" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/row_background" android:foreground="@drawable/foreground_row"> ... </FrameLayout> 

而我想要的东西是这样的:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/cardContent" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/row_background" app:foreground="@drawable/foreground_row"> ... </RelativeLayout> 

提前致谢!!

这个想法是用一个FrameLayout环绕你的布局,并将select器和onClick事件设置为这个布局。

 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/selectableItem" android:layout_width="wrap_content" android:layout_height="wrap_content" android:foreground="@drawable/foreground_row" > <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/cardContent" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/row_background"> ... </RelativeLayout> </FrameLayout> 

你可以在我的博客find完整的解释:

http://antonioleiva.com/unveiling-bandhook-foreground-any-layout/

或者你可以扩展rhis FRelativeLayout https://gist.github.com/shakalaca/6199283

这是一个可能的实现,也支持检查布局。

一个几乎相同的解决scheme可以应用到你想要的任何布局视图(只有CTOR是不同的)。

 public class CheckableLinearLayout extends LinearLayout implements Checkable { private boolean mChecked; private static final String TAG = CheckableLinearLayout.class.getCanonicalName(); private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked }; private Drawable mForeground; public CheckableLinearLayout(final Context context) { this(context, null, 0); } public CheckableLinearLayout(final Context context, final AttributeSet attrs) { this(context, attrs, 0); } public CheckableLinearLayout(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); final TypedArray a = context .obtainStyledAttributes(attrs, R.styleable.CheckableLinearLayout, defStyle, 0); setForeground(a.getDrawable(R.styleable.CheckableLinearLayout_foreground)); a.recycle(); } public void setForeground(final Drawable drawable) { this.mForeground = drawable; } @Override protected int[] onCreateDrawableState(final int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Override protected void drawableStateChanged() { super.drawableStateChanged(); final Drawable drawable = getBackground(); boolean needRedraw = false; final int[] myDrawableState = getDrawableState(); if (drawable != null) { drawable.setState(myDrawableState); needRedraw = true; } if (mForeground != null) { mForeground.setState(myDrawableState); needRedraw = true; } if (needRedraw) invalidate(); } @Override protected void onSizeChanged(final int width, final int height, final int oldwidth, final int oldheight) { super.onSizeChanged(width, height, oldwidth, oldheight); if (mForeground != null) mForeground.setBounds(0, 0, width, height); } @Override protected void dispatchDraw(final Canvas canvas) { super.dispatchDraw(canvas); if (mForeground != null) mForeground.draw(canvas); } @Override public boolean isChecked() { return mChecked; } @Override public void setChecked(final boolean checked) { mChecked = checked; refreshDrawableState(); //TODO think if you wish to also check inner views, maybe even recursively } @Override public void toggle() { setChecked(!mChecked); } @Override public Parcelable onSaveInstanceState() { // Force our ancestor class to save its state final Parcelable superState = super.onSaveInstanceState(); final SavedState savedState = new SavedState(superState); savedState.checked = isChecked(); return savedState; } @Override public void onRestoreInstanceState(final Parcelable state) { final SavedState savedState = (SavedState) state; super.onRestoreInstanceState(savedState.getSuperState()); setChecked(savedState.checked); requestLayout(); } @SuppressLint("ClickableViewAccessibility") @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public boolean onTouchEvent(final MotionEvent e) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && // e.getActionMasked() == MotionEvent.ACTION_DOWN && // mForeground != null) mForeground.setHotspot(e.getX(), e.getY()); return super.onTouchEvent(e); } // ///////////// // SavedState // // ///////////// private static class SavedState extends BaseSavedState { boolean checked; SavedState(final Parcelable superState) { super(superState); } private SavedState(final Parcel in) { super(in); checked = (Boolean) in.readValue(null); } @Override public void writeToParcel(final Parcel out, final int flags) { super.writeToParcel(out, flags); out.writeValue(checked); } @Override public String toString() { return TAG + ".SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } @SuppressWarnings("unused") public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { @Override public SavedState createFromParcel(final Parcel in) { return new SavedState(in); } @Override public SavedState[] newArray(final int size) { return new SavedState[size]; } }; } } 

使用Gradle集成检出ForegroundView库。 它支持以下视图

  • ForegroundImageView
  • ForegroundButton
  • ForegroundTextView
  • ForegroundImageButton
  • ForegroundEditText
  • ForegroundWebView
  • ForegroundLinearLayout
  • ForegroundRelativeLayout
  • ForegroundGridLayout
  • ForegroundGridView
  • ForegroundHorizo​​ntalScrollView
  • ForegroundListView
  • ForegroundScrollViewForegroundImageView