我有一个带有KenBurnsView和ImageView的布局(只是一个切换按钮)。当我点击按钮时,会生成一个Ripple但是会在KenBurnsView下面绘制。
以前,当我将图像视图替换为KenBurnsView时,Ripple被绘制在顶部的ImageView上方。
这是我的布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background"
android:clickable="true"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="@dimen/nav_drawer_header_height">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.flaviofaria.kenburnsview.KenBurnsView
android:id="@+id/header_cover"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/cover_1" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/header_toggle"
android:layout_width="50dp"
android:layout_height="30dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="10dp"
android:layout_marginRight="10dp"
android:padding="10dp"
android:src="@drawable/toggle_down" />
</RelativeLayout>
</FrameLayout>
</RelativeLayout>
<RelativeLayout
android:id="@+id/nav_toggle_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></RelativeLayout>
</LinearLayout>
这是我的涟漪可绘XML:
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@android:color/white"
android:drawSelectorOnTop="true"> <!-- ripple color -->
</ripple>
这是我添加涟漪的方式:
toggle.setBackground(getResources().getDrawable(R.drawable.ripple));
问题是什么,因为Ripple在KenBurnsView下面得到了什么?当有一个ImageView代替KenBurnsView时,它曾经很好地工作吗?
答案 0 :(得分:3)
无限的涟漪投射到祖先视图的第一个可用背景上。从托管涟漪的ImageView
跟踪视图层次结构,您会发现第一个可用背景位于LinearLayout
,标识为drawer
。
如果您在包含RelativeLayout
的{{1}}上设置透明背景,则第一个可用的背景将是在兄弟视图上方呈现的背景,您将获得所需的效果。
旁注,ImageView
应替换为RelativeLayout
,这样可以提供与较便宜的布局传递相同的效果。
答案 1 :(得分:3)
我从@Budius的答案中获得了灵感和帮助,并创造了一个更好的解决方案。
ImageView使用一个hack,即使你将它设置为背景(使用setBackgroundDrawable()),它也允许RippleDrawable绘制它。
我创建了一个具有绘制前景的功能的修改后的ImageView,
public class ForegroundImageView extends ImageView {
private Drawable foreground;
public ForegroundImageView(Context context) {
this(context, null);
}
public ForegroundImageView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ForegroundImageView);
Drawable foreground = a.getDrawable(R.styleable.ForegroundImageView_android_foreground);
if (foreground != null) {
setForeground(foreground);
}
a.recycle();
}
/**
* Supply a drawable resource that is to be rendered on top of all of the child
* views in the frame layout.
*
* @param drawableResId The drawable resource to be drawn on top of the children.
*/
public void setForegroundResource(int drawableResId) {
setForeground(getContext().getResources().getDrawable(drawableResId));
}
/**
* Supply a Drawable that is to be rendered on top of all of the child
* views in the frame layout.
*
* @param drawable The Drawable to be drawn on top of the children.
*/
public void setForeground(Drawable drawable) {
if (foreground == drawable) {
return;
}
if (foreground != null) {
foreground.setCallback(null);
unscheduleDrawable(foreground);
}
foreground = drawable;
if (drawable != null) {
drawable.setCallback(this);
if (drawable.isStateful()) {
drawable.setState(getDrawableState());
}
}
requestLayout();
invalidate();
}
@Override
protected boolean verifyDrawable(Drawable who) {
return super.verifyDrawable(who) || who == foreground;
}
@Override
public void jumpDrawablesToCurrentState() {
super.jumpDrawablesToCurrentState();
if (foreground != null) foreground.jumpToCurrentState();
}
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
if (foreground != null && foreground.isStateful()) {
foreground.setState(getDrawableState());
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (foreground != null) {
foreground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
invalidate();
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (foreground != null) {
foreground.setBounds(0, 0, w, h);
invalidate();
}
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
if (foreground != null) {
foreground.draw(canvas);
}
}
}
然后我将切换图像放在此图像视图中,并以编程方式应用了纹波
toggle.setForegroundResource(R.drawable.ripple);
这将使波纹在此特定视图的范围内绘制。要使波纹划过其他视图,
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false">
您需要为clipChildren和clipToPadding添加false。
希望这有助于有人解决问题。
答案 2 :(得分:0)
正如您可以从自己的代码中看到的那样(&#39; setBackground&#39;),您将涟漪设置为背景,这就是为什么它的原因。在背景上绘制。
Android API 21上的ImageView添加了这个&#34; hack&#34;对于涟漪android:drawSelectorOnTop="true"
。但是你使用的图书馆并没有添加相同的黑客。
您的代码本身并没有错。但Android团队无法保证第三方库的这种行为。
您可以在此处选择一些清洁度,努力程度和性能的选项:
KenBurnsView
并使用FrameLayout上的setForeground
设置涟漪。