问题
I have a 9 patch drawable which I want to use as a background on a view. I want the view to show a ripple effect that follows the outline of a 9 patch when the view is clicked. Here's my activity, layout, and drawable code.
MainActivity.kt:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val click = findViewById<ConstraintLayout>(R.id.container)
click.setOnClickListener { Toast.makeText(this, "Clicked", Toast.LENGTH_SHORT).show() }
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.antonc.testapp.MainActivity">
<android.support.constraint.ConstraintLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:paddingTop="16dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:background="@drawable/tooltip_background"
android:backgroundTint="#2681d8"
tools:layout_editor_absoluteX="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello test test !!!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintHorizontal_bias="0.0"
/>
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
tooltip_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#33000000">
<item android:drawable="@drawable/tooltip_left_top"/>
<item android:id="@android:id/mask" android:drawable="@drawable/tooltip_left_top"/>
</ripple>
tooltip_left_top.9.png:
But when I click on it, the ripple drawable is very distorted, as if it's stretched to the view size without observing the stretch rules of 9 patch. How should I configure the ripple to make it be the same as the background?:
回答1:
Update: I have reworked the answer to refine the issue. The following has been edited to reflect the changes.
TL;DR Do not use android:backgroundTint
for ripple backgrounds based on nine-patch drawables at least for API 28. Set the tint in code.
This issue has something to do with the background tint. I will explain how I came to this conclusion by referring to the following video.
I will refer to the bubbles as view1 through view4 from top to bottom. I changed from your nine-patch to better see the patches since your nine-patch was mostly black.
View1, when click, shows the appropriate ripple effect. It has a ripple background but no background tint.
View2 is what you are seeing with your background - it is just messed up. This view has a background tint set in XML.
The height of view3 has been forced to the height of view1 to see how the ripple looks. As you can see, the ripple looks right for the height. It is the non-ripple background image that is distorted.
View4 is the same as view2 except that it has the tint for RippleDrawable
added programmatically. As you can see, this view looks and behaves as it should.
Bottom line? Don't set the background tint for a nine-patch in XML. Set it in code. Is this a bug? Maybe.
Here is the support code for the video above.
activity_main.xml
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFFFF"
android:fillViewport="true"
android:orientation="vertical"
android:padding="16dp"
tools:context=".MainActivity">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:context=".MainActivity">
<ImageView
android:id="@+id/imageView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:background="@drawable/bubble_background"
android:clickable="true" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:background="@drawable/bubble_background"
android:backgroundTint="@color/background_tint"
android:clickable="true" />
<ImageView
android:id="@+id/imageView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:background="@drawable/bubble_background"
android:backgroundTint="@color/background_tint"
android:clickable="true" />
<ImageView
android:id="@+id/imageView4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:background="@drawable/bubble_background"
android:clickable="true" />
</LinearLayout>
</ScrollView>
bubble_background.xml
<ripple
android:color="#33000000">
<item android:drawable="@drawable/ninepatch_bubble">
</item>
</ripple>
MainActivity.java
public class MainActivity extends AppCompatActivity {
private LinearLayout mLayout;
private ImageView mImageView1;
private ImageView mImageView2;
private ImageView mImageView3;
private ImageView mImageView4;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLayout = findViewById(R.id.layout);
mImageView1 = findViewById(R.id.imageView1);
mImageView2 = findViewById(R.id.imageView2);
mImageView3 = findViewById(R.id.imageView3);
mImageView4 = findViewById(R.id.imageView4);
int bgTint = getResources().getColor(R.color.background_tint);
RippleDrawable rippleDrawable =(RippleDrawable) mImageView4.getBackground();
rippleDrawable.getDrawable(0).setTint(bgTint);
mImageView4.setBackground(rippleDrawable);
mLayout.post(new Runnable() {
@Override
public void run() {
mImageView3.getLayoutParams().height = mImageView1.getMeasuredHeight();
mLayout.requestLayout();
}
});
}
}
colors.xml
These were added to colors.xml:
<color name="background_tint">#2681d8</color>
<color name="ripple_tint">#33000000</color>
ninepatch_bubble.9.png
回答2:
Try to use ripple effect like this:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/White">
<item android:drawable="@drawable/tooltip_left_top" />
<item android:id="@android:id/mask">
<color android:color="@color/your_tooltip_color_code" />
</item>
</ripple>
Update here if it works.
来源:https://stackoverflow.com/questions/52672483/ripple-effect-drawable-is-distorted-when-applied-over-9patch-background