N S*_*rma 165 android material-design
我想在按钮点击上添加一个涟漪动画.我确实喜欢下面但它需要minSdKVersion到21.
ripple.xml
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight">
<item>
<shape android:shape="rectangle">
<solid android:color="?android:colorAccent" />
</shape>
</item>
</ripple>
Run Code Online (Sandbox Code Playgroud)
按键
<com.devspark.robototextview.widget.RobotoButton
android:id="@+id/loginButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/ripple"
android:text="@string/login_button" />
Run Code Online (Sandbox Code Playgroud)
我想让它向后兼容设计库.
怎么做到这一点?
Ben*_*aye 362
基本纹波设置
视图中包含的涟漪.
android:background="?selectableItemBackground"
超出视图范围的涟漪:
android:background="?selectableItemBackgroundBorderless"
看看这里解决?(attr)Java代码中的xml引用.
支持库
?attr:(或?简写)代替?android:attr引用支持库,因此可以返回到API 7.涟漪与图像/背景
View在一个FrameLayout与设置的波纹setForeground()或setBackground().老实说,除此之外没有干净的方式这样做,尽管尼克布彻在涟漪的主题上发布了这个android:background="?selectableItemBackground".
Mar*_*ski 54
我之前投票决定将这个问题作为主题关闭但实际上我改变了主意,因为这是非常好的视觉效果,遗憾的是,它还不是支持库的一部分.它很可能会在未来的更新中出现,但没有宣布时间框架.
幸运的是,现有的自定义实现很少:
包括与旧版Android兼容的Materlial主题小部件集:
所以你可以尝试其中一个或谷歌的其他"材料小部件"左右...
Nic*_*ler 27
我做了一个简单的类来制作波纹按钮,我最后从不需要它,所以它不是最好的,但它在这里是:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Button;
public class RippleView extends Button
{
private float duration = 250;
private float speed = 1;
private float radius = 0;
private Paint paint = new Paint();
private float endRadius = 0;
private float rippleX = 0;
private float rippleY = 0;
private int width = 0;
private int height = 0;
private OnClickListener clickListener = null;
private Handler handler;
private int touchAction;
private RippleView thisRippleView = this;
public RippleView(Context context)
{
this(context, null, 0);
}
public RippleView(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public RippleView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
init();
}
private void init()
{
if (isInEditMode())
return;
handler = new Handler();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
paint.setAntiAlias(true);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
}
@Override
protected void onDraw(@NonNull Canvas canvas)
{
super.onDraw(canvas);
if(radius > 0 && radius < endRadius)
{
canvas.drawCircle(rippleX, rippleY, radius, paint);
if(touchAction == MotionEvent.ACTION_UP)
invalidate();
}
}
@Override
public boolean onTouchEvent(@NonNull MotionEvent event)
{
rippleX = event.getX();
rippleY = event.getY();
switch(event.getAction())
{
case MotionEvent.ACTION_UP:
{
getParent().requestDisallowInterceptTouchEvent(false);
touchAction = MotionEvent.ACTION_UP;
radius = 1;
endRadius = Math.max(Math.max(Math.max(width - rippleX, rippleX), rippleY), height - rippleY);
speed = endRadius / duration * 10;
handler.postDelayed(new Runnable()
{
@Override
public void run()
{
if(radius < endRadius)
{
radius += speed;
paint.setAlpha(90 - (int) (radius / endRadius * 90));
handler.postDelayed(this, 1);
}
else
{
clickListener.onClick(thisRippleView);
}
}
}, 10);
invalidate();
break;
}
case MotionEvent.ACTION_CANCEL:
{
getParent().requestDisallowInterceptTouchEvent(false);
touchAction = MotionEvent.ACTION_CANCEL;
radius = 0;
invalidate();
break;
}
case MotionEvent.ACTION_DOWN:
{
getParent().requestDisallowInterceptTouchEvent(true);
touchAction = MotionEvent.ACTION_UP;
endRadius = Math.max(Math.max(Math.max(width - rippleX, rippleX), rippleY), height - rippleY);
paint.setAlpha(90);
radius = endRadius/4;
invalidate();
return true;
}
case MotionEvent.ACTION_MOVE:
{
if(rippleX < 0 || rippleX > width || rippleY < 0 || rippleY > height)
{
getParent().requestDisallowInterceptTouchEvent(false);
touchAction = MotionEvent.ACTION_CANCEL;
radius = 0;
invalidate();
break;
}
else
{
touchAction = MotionEvent.ACTION_MOVE;
invalidate();
return true;
}
}
}
return false;
}
@Override
public void setOnClickListener(OnClickListener l)
{
clickListener = l;
}
}
Run Code Online (Sandbox Code Playgroud)
编辑
由于很多人都在寻找这样的东西,我创造了一个可以让其他观点产生连锁反应的课程:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
public class RippleViewCreator extends FrameLayout
{
private float duration = 150;
private int frameRate = 15;
private float speed = 1;
private float radius = 0;
private Paint paint = new Paint();
private float endRadius = 0;
private float rippleX = 0;
private float rippleY = 0;
private int width = 0;
private int height = 0;
private Handler handler = new Handler();
private int touchAction;
public RippleViewCreator(Context context)
{
this(context, null, 0);
}
public RippleViewCreator(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public RippleViewCreator(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
init();
}
private void init()
{
if (isInEditMode())
return;
paint.setStyle(Paint.Style.FILL);
paint.setColor(getResources().getColor(R.color.control_highlight_color));
paint.setAntiAlias(true);
setWillNotDraw(true);
setDrawingCacheEnabled(true);
setClickable(true);
}
public static void addRippleToView(View v)
{
ViewGroup parent = (ViewGroup)v.getParent();
int index = -1;
if(parent != null)
{
index = parent.indexOfChild(v);
parent.removeView(v);
}
RippleViewCreator rippleViewCreator = new RippleViewCreator(v.getContext());
rippleViewCreator.setLayoutParams(v.getLayoutParams());
if(index == -1)
parent.addView(rippleViewCreator, index);
else
parent.addView(rippleViewCreator);
rippleViewCreator.addView(v);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
}
@Override
protected void dispatchDraw(@NonNull Canvas canvas)
{
super.dispatchDraw(canvas);
if(radius > 0 && radius < endRadius)
{
canvas.drawCircle(rippleX, rippleY, radius, paint);
if(touchAction == MotionEvent.ACTION_UP)
invalidate();
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event)
{
return true;
}
@Override
public boolean onTouchEvent(@NonNull MotionEvent event)
{
rippleX = event.getX();
rippleY = event.getY();
touchAction = event.getAction();
switch(event.getAction())
{
case MotionEvent.ACTION_UP:
{
getParent().requestDisallowInterceptTouchEvent(false);
radius = 1;
endRadius = Math.max(Math.max(Math.max(width - rippleX, rippleX), rippleY), height - rippleY);
speed = endRadius / duration * frameRate;
handler.postDelayed(new Runnable()
{
@Override
public void run()
{
if(radius < endRadius)
{
radius += speed;
paint.setAlpha(90 - (int) (radius / endRadius * 90));
handler.postDelayed(this, frameRate);
}
else if(getChildAt(0) != null)
{
getChildAt(0).performClick();
}
}
}, frameRate);
break;
}
case MotionEvent.ACTION_CANCEL:
{
getParent().requestDisallowInterceptTouchEvent(false);
break;
}
case MotionEvent.ACTION_DOWN:
{
getParent().requestDisallowInterceptTouchEvent(true);
endRadius = Math.max(Math.max(Math.max(width - rippleX, rippleX), rippleY), height - rippleY);
paint.setAlpha(90);
radius = endRadius/3;
invalidate();
return true;
}
case MotionEvent.ACTION_MOVE:
{
if(rippleX < 0 || rippleX > width || rippleY < 0 || rippleY > height)
{
getParent().requestDisallowInterceptTouchEvent(false);
touchAction = MotionEvent.ACTION_CANCEL;
break;
}
else
{
invalidate();
return true;
}
}
}
invalidate();
return false;
}
@Override
public final void addView(@NonNull View child, int index, ViewGroup.LayoutParams params)
{
//limit one view
if (getChildCount() > 0)
{
throw new IllegalStateException(this.getClass().toString()+" can only have one child.");
}
super.addView(child, index, params);
}
}
Run Code Online (Sandbox Code Playgroud)
Ami*_*bar 12
这很简单;-)
首先,您必须创建两个可绘制文件,一个用于旧api版本,另一个用于最新版本,当然!如果您为最新的api版本android studio创建drawable文件,建议您自动创建旧的。最后将此可绘制对象设置为背景视图。
适用于新api版本(res / drawable-v21 / ripple.xml)的示例可绘制对象:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight">
<item>
<shape android:shape="rectangle">
<solid android:color="@color/colorPrimary" />
<corners android:radius="@dimen/round_corner" />
</shape>
</item>
</ripple>
Run Code Online (Sandbox Code Playgroud)
适用于旧api版本的示例可绘制样本(res / drawable / ripple.xml)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/colorPrimary" />
<corners android:radius="@dimen/round_corner" />
</shape>
Run Code Online (Sandbox Code Playgroud)
有关波纹可绘制的更多信息,请访问:https : //developer.android.com/reference/android/graphics/drawable/RippleDrawable.html
小智 11
有时您具有自定义背景,在这种情况下,使用更好的解决方案 android:foreground="?selectableItemBackground"
| 归档时间: |
|
| 查看次数: |
131956 次 |
| 最近记录: |