我试图了解如何实现按钮和其他视图的“连锁反应-触摸反馈”。我研究了与SO上的涟漪触摸效应相关的问题,并对其进行了一些深入了解。我能够使用这个java代码成功地获得连锁反应。
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RadialGradient;
import android.graphics.Region;
import android.graphics.Shader;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.AccelerateInterpolator;
import android.widget.Button;
public class MyButton extends Button {
private float mDownX;
private float mDownY;
private float mRadius;
private Paint mPaint;
public MyButton(final Context context) {
super(context);
init();
}
public MyButton(final Context context, final AttributeSet attrs) {
super(context, attrs);
init();
}
public MyButton(final Context context, final AttributeSet attrs,
final int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setAlpha(100);
}
@Override
public boolean onTouchEvent(@NonNull final MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_UP) {
mDownX = event.getX();
mDownY = event.getY();
ObjectAnimator animator = ObjectAnimator.ofFloat(this, "radius", 0,
getWidth() * 3.0f);
animator.setInterpolator(new AccelerateInterpolator());
animator.setDuration(400);
animator.start();
}
return super.onTouchEvent(event);
}
public void setRadius(final float radius) {
mRadius = radius;
if (mRadius > 0) {
RadialGradient radialGradient = new RadialGradient(mDownX, mDownY,
mRadius * 3, Color.TRANSPARENT, Color.BLACK,
Shader.TileMode.MIRROR);
mPaint.setShader(radialGradient);
}
invalidate();
}
private Path mPath = new Path();
private Path mPath2 = new Path();
@Override
protected void onDraw(@NonNull final Canvas canvas) {
super.onDraw(canvas);
mPath2.reset();
mPath2.addCircle(mDownX, mDownY, mRadius, Path.Direction.CW);
canvas.clipPath(mPath2);
mPath.reset();
mPath.addCircle(mDownX, mDownY, mRadius / 3, Path.Direction.CW);
canvas.clipPath(mPath, Region.Op.DIFFERENCE);
canvas.drawCircle(mDownX, mDownY, mRadius, mPaint);
}
}
但是,我想使用XML方法。我如何实现这一点?我看了这个和这个,但是我对风格还不太满意,所以我发现很难达到涟漪效应。
我有一个包含以下XML代码的按钮:
<Button
android:id="@+id/button_email"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="0.50"
android:gravity="center"
android:text="@string/email" />
我如何得到这个按钮的涟漪效应。如果有人能指引我,我将心存感激。
[编辑]添加ripple.xml和background.xml,如上面的链接之一所述。我在res中创建了一个绘图v21文件夹,并在那里添加了以下文件。
涟漪xml
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@android:color/black" >
<item android:drawable="@drawable/background">
</item>
</ripple>
出身背景xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="@android:color/darker_gray" />
</shape>
我添加了ripple作为我按钮的背景,下面是我按钮的xml。。
<Button
android:id="@+id/button_email"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="0.50"
android:gravity="center"
android:background="@drawable/ripple"
android:text="@string/email" />
当我运行应用程序时,我得到一个ResourceNotFoundException。这是日志跟踪。。
07-21 17:03:39.043: E/AndroidRuntime(15710): FATAL EXCEPTION: main
07-21 17:03:39.043: E/AndroidRuntime(15710): Process: com.xx.xxx, PID: 15710
07-21 17:03:39.043: E/AndroidRuntime(15710): android.view.InflateException: Binary XML file line #60: Error inflating class <unknown>
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.LayoutInflater.createView(LayoutInflater.java:620)
07-21 17:03:39.043: E/AndroidRuntime(15710): at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.LayoutInflater.onCreateView(LayoutInflater.java:669)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:694)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.LayoutInflater.rInflate(LayoutInflater.java:755)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.LayoutInflater.rInflate(LayoutInflater.java:758)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
07-21 17:03:39.043: E/AndroidRuntime(15710): at com.xx.xxx.BusinessAdapter.onCreateViewHolder(BusinessAdapter.java:106)
07-21 17:03:39.043: E/AndroidRuntime(15710): at com.xx.xxx.BusinessAdapter.onCreateViewHolder(BusinessAdapter.java:1)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:2915)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:2511)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.support.v7.widget.LinearLayoutManager$RenderState.next(LinearLayoutManager.java:1425)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:999)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:524)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:1461)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:1600)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.View.layout(View.java:14817)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.ViewGroup.layout(ViewGroup.java:4631)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.View.layout(View.java:14817)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.ViewGroup.layout(ViewGroup.java:4631)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.View.layout(View.java:14817)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.ViewGroup.layout(ViewGroup.java:4631)
07-21 17:03:39.043: E/AndroidRuntime(15710): at com.android.internal.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:374)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.View.layout(View.java:14817)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.ViewGroup.layout(ViewGroup.java:4631)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.View.layout(View.java:14817)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.ViewGroup.layout(ViewGroup.java:4631)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1983)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1740)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:996)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5600)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.Choreographer.doCallbacks(Choreographer.java:574)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.Choreographer.doFrame(Choreographer.java:544)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.os.Handler.handleCallback(Handler.java:733)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.os.Handler.dispatchMessage(Handler.java:95)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.os.Looper.loop(Looper.java:136)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.app.ActivityThread.main(ActivityThread.java:5001)
07-21 17:03:39.043: E/AndroidRuntime(15710): at java.lang.reflect.Method.invokeNative(Native Method)
07-21 17:03:39.043: E/AndroidRuntime(15710): at java.lang.reflect.Method.invoke(Method.java:515)
07-21 17:03:39.043: E/AndroidRuntime(15710): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
07-21 17:03:39.043: E/AndroidRuntime(15710): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
07-21 17:03:39.043: E/AndroidRuntime(15710): at dalvik.system.NativeStart.main(Native Method)
07-21 17:03:39.043: E/AndroidRuntime(15710): Caused by: java.lang.reflect.InvocationTargetException
07-21 17:03:39.043: E/AndroidRuntime(15710): at java.lang.reflect.Constructor.constructNative(Native Method)
07-21 17:03:39.043: E/AndroidRuntime(15710): at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.LayoutInflater.createView(LayoutInflater.java:594)
07-21 17:03:39.043: E/AndroidRuntime(15710): ... 50 more
07-21 17:03:39.043: E/AndroidRuntime(15710): Caused by: android.content.res.Resources$NotFoundException: Resource is not a Drawable (color or path): TypedValue{t=0x1/d=0x7f020075 a=-1 r=0x
对于Lollipop(API
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:color="?android:colorAccent"
tools:targetApi="lollipop">
<item android:drawable="@color/cancel_btn_clr" /> <!-- default -->
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="?android:colorAccent" />
</shape>
</item>
</ripple>
对于预Lollipop(API
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape>
<solid android:color="@color/colorAccent"></solid>
</shape>
</item>
<item>
<shape>
<solid android:color="@color/cancel_btn_clr"></solid>
</shape>
</item>
</selector>
只要把?API 21按钮背景中的attr/selectableItemBackground
,如下所示:
<Button
android:layout_width="match_parent"
android:layout_height="70dp"
android:background="?attr/selectableItemBackground"
android:text="Button" />
更新材料组件:
使用材质组件库可以很容易地应用纹波。
只需使用MaterialButton
和app: rypleColor
属性:
<com.google.android.material.button.MaterialButton
app:rippleColor="@color/my_selector"
../>
使用如下选择器:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="..." android:color="?attr/colorOnPrimary" android:state_pressed="true"/>
<item android:alpha="..." android:color="?attr/colorOnPrimary" android:state_focused="true" android:state_hovered="true"/>
<item android:alpha="..." android:color="?attr/colorOnPrimary" android:state_focused="true"/>
<item android:alpha="..." android:color="?attr/colorOnPrimary" android:state_hovered="true"/>
<item android:alpha="..." android:color="?attr/colorOnPrimary"/>
</selector>
旧答案
你可以这样做:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ripple"
/>
涟漪在哪里。xml是:
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight">
<item android:id="@android:id/mask">
<shape android:shape="oval">
<solid android:color="?android:colorAccent" />
</shape>
</item>
</ripple>
好的,所以我知道涟漪效应是唯一可用的Lollipop和以上。但是,当设置ImageButton时,我仍然无法获得像“常规”按钮一样的涟漪效果,只显示一个图像(和透明bg)。。。 我添加了AppCompat v7,并将第二个布局放在我的drawable/layout-v21文件夹中,该文件夹中有以下按钮: 但背景是灰色的,纹波(也是灰色的)无法定制。 所以,如果我只需要一个很好的ripple dra
我想在我的应用程序中使用水波涟漪效果,这种效果会在触摸区域反复出现,我已经访问了站点中可用的示例代码,但涟漪似乎被像素化了。 谁能帮我,实现活水涟漪效应?。我发现很难实施它。
我一直在为Lollipop(API 21)开发一个应用程序。 XML:
我有一个带有仰角的圆角矩形,它投射了一个阴影,就像这里的示例:http://developer.android.com/preview/material/views-shadows.html#shadows 下面是我的形状: 我想获得其他所有东西都有的漂亮的“涟漪”触摸效果,但当它被设置为视图的背景时,没有触摸反馈。形状保持白色。 有办法解决这个问题吗?第一个链接的部分似乎是我想要的,但我不知道如
我有一个,它扩展了以下网格项: 但是涟漪效应不会出现,除非我将可见性设置为不可见。似乎涟漪效应是在下方绘制的。如何在上绘制?
我有两个有棱角的材质按钮。我的目标是以编程方式让按钮在按下某个键时产生涟漪。 看看stack blitz项目:https://stackblitz.com/edit/angular-material-button-vphppo 有没有一种方法可以让按钮在点击或按键的同时产生波纹? 我尝试了这些示例如何在Angular MatListItem上以编程方式触发涟漪效应? 但这会让按钮在点击时产生两次涟