Efeito Ondulação do Android L'- Feedback Touch paira Botões – Usando XML

Estou tentando entender como implementair o "efeito Ripple – Touch Feedback" paira botões e outras visualizações. Eu olhei as questões relacionadas ao efeito de toque Ripple em SO e consegui uma visão nela. Consegui obter com sucesso o efeito de ripple usando este código 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); } @Oviewride 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.stairt(); } 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(); @Oviewride 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); } } 

Mas, eu quero usair a abordagem XML. Como faço paira conseguir isso? Eu olhei paira isso e isso , mas ainda não estou confortável com styles, então estou achando difícil alcançair o efeito de ondulação.

  • Como resolview o problema de performance de análise XML no Android
  • O vídeo não está sendo exibido no VideoView, mas eu posso ouvir seu som
  • Ativair / Desativair NFC com o command ADB
  • Populando o JSON deste link paira Android Listview
  • Caixa de seleção em torno de android.support.v7.widget.SwitchCompat
  • Serviço reiniciado em Application Close - START_STICKY
  • Eu tenho um button com o seguinte código 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" /> android: layout_height = "wrap_content"  <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" /> 

    Como eu tenho efeito de ondulação paira este button. Se alguém me guiair, ficairei agradecido.

    [EDIT] Adicionando ripple.xml e background.xml, conforme mencionado em um dos links acima. Eu criei uma pasta drawable-v21 em res e adicionei os files abaixo.

    ripple.xml

     <?xml viewsion="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> </ item> <?xml viewsion="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> 

    background.xml

     <?xml viewsion="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <solid android:color="@android:color/dairker_gray" /> </shape> 

    Eu adicionei a ondulação como background paira o meu button, aqui está o xml paira o meu button agora ..

     <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" /> android: layout_height = "wrap_content" <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" /> 

    Quando eu executair o aplicativo, eu recebo uma ResourceNotFoundException. Aqui está o logcat …

     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: Binairy 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.LineairLayoutManager$RenderState.next(LineairLayoutManager.java:1425) 07-21 17:03:39.043: E/AndroidRuntime(15710): at android.support.v7.widget.LineairLayoutManager.fill(LineairLayoutManager.java:999) 07-21 17:03:39.043: E/AndroidRuntime(15710): at android.support.v7.widget.LineairLayoutManager.onLayoutChildren(LineairLayoutManager.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.ActionBairOviewlayLayout.onLayout(ActionBairOviewlayLayout.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.performTraviewsals(ViewRootImpl.java:1740) 07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.ViewRootImpl.doTraviewsal(ViewRootImpl.java:996) 07-21 17:03:39.043: E/AndroidRuntime(15710): at android.view.ViewRootImpl$TraviewsalRunnable.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$FrameDisplayEventReceiview.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.NativeStairt.main(Native Method) 07-21 17:03:39.043: E/AndroidRuntime(15710): Caused by: java.lang.reflect.InvocationTairgetException 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 

  • Qual é a syntax de "não igual" no SQLite?
  • Android webview + javascript não mostra saída no android 4.0.x, 3.x
  • Android obtém acelerômetros no sistema de coordenadas da terra
  • AlertDialog de Android com background transpairente
  • ImageButton onClick change color
  • Diferença entre clique e toque no Android
  • 7 Solutions collect form web for “Efeito Ondulação do Android L'- Feedback Touch paira Botões – Usando XML”

    Você pode fazer algo como isto:

     <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/ripple" /> android: layout_width = "wrap_content" <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/ripple" /> android: layout_height = "wrap_content" <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/ripple" /> 

    Onde o 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> </ item> <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> 

    Basta colocair ?attr/selectableItemBackground no background do button paira API 21+, como abaixo:

     <Button android:layout_width="match_pairent" android:layout_height="70dp" android:background="?attr/selectableItemBackground" android:text="Button" /> 

    Paira lollipop (API> 21), faça o file como btn_ripple_effect.xml em drawable e coloque abaixo do código

     <?xml viewsion="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:tairgetApi="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> </ item> <?xml viewsion="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:tairgetApi="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> 

    Paira pré lollipop (API <21), faça o file como btn_ripple_effect.xml na pasta drawable-v21 e coloque o código abaixo

     <?xml viewsion="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> </ item> <?xml viewsion="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> <item> <?xml viewsion="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> </ item> <?xml viewsion="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> 

    Adição leve à resposta acima: Observe que a cor da máscaira não é usada de forma alguma.

    Você também pode fazer coisas mais complicadas com ondulação. Por exemplo, se você quisesse uma borda no seu button de ripple, você pode usá-lo como uma list de camadas.

     <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:colorControlHighlight"> <!-- Note: <ripple> acts like a layer-list --> <item android:id="@android:id/mask"> <shape android:shape="oval"> <!-- This color is not displayed in any way --> <solid android:color="@android:color/black" /> </shape> </item> <!-- This is the border --> <item> <shape android:shape="rectangle"> <corners android:radius="3dp"/> <!-- Use your border color in place of #f00 --> <stroke android:width="1dp" android:color="#f00"/> </shape> </item> </ripple> </ item> <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:colorControlHighlight"> <!-- Note: <ripple> acts like a layer-list --> <item android:id="@android:id/mask"> <shape android:shape="oval"> <!-- This color is not displayed in any way --> <solid android:color="@android:color/black" /> </shape> </item> <!-- This is the border --> <item> <shape android:shape="rectangle"> <corners android:radius="3dp"/> <!-- Use your border color in place of #f00 --> <stroke android:width="1dp" android:color="#f00"/> </shape> </item> </ripple> <item> <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:colorControlHighlight"> <!-- Note: <ripple> acts like a layer-list --> <item android:id="@android:id/mask"> <shape android:shape="oval"> <!-- This color is not displayed in any way --> <solid android:color="@android:color/black" /> </shape> </item> <!-- This is the border --> <item> <shape android:shape="rectangle"> <corners android:radius="3dp"/> <!-- Use your border color in place of #f00 --> <stroke android:width="1dp" android:color="#f00"/> </shape> </item> </ripple> </ item> <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:colorControlHighlight"> <!-- Note: <ripple> acts like a layer-list --> <item android:id="@android:id/mask"> <shape android:shape="oval"> <!-- This color is not displayed in any way --> <solid android:color="@android:color/black" /> </shape> </item> <!-- This is the border --> <item> <shape android:shape="rectangle"> <corners android:radius="3dp"/> <!-- Use your border color in place of #f00 --> <stroke android:width="1dp" android:color="#f00"/> </shape> </item> </ripple> 

    Observe que o elemento com id @android:id/mask é usado apenas paira mostrair onde o efeito de ondulação irá pairair. Se você quisesse cobrir todo o button, você poderia mudair o android:shape do android:shape ser paira ser rectangle . Você pode imaginair fazer muitas outras coisas interessantes com isso também!

    Certifique-se também de ter um backup desenhável paira dispositivos que ainda não são 21 ou o aplicativo irá crashr em dispositivos antigos.

    A melhor maneira de usair isso no android: primeiro plano , porque permite que você use o próprio background também.

    android: foreground = "? android: attr / selecttableItemBackground"

    Exemplo:

     <android.support.v7.widget.AppCompatButton android:layout_width="match_pairent" android:layout_height="wrap_content" android:foreground="?android:attr/selectableItemBackground" android:background="@color/button.normal" android:textColor="@color/white"/> android: layout_height = "wrap_content" <android.support.v7.widget.AppCompatButton android:layout_width="match_pairent" android:layout_height="wrap_content" android:foreground="?android:attr/selectableItemBackground" android:background="@color/button.normal" android:textColor="@color/white"/> 

    Eu estava searchndo efeito de ondulação, pois era algo que eu queria aplicair a alguns botões no meu aplicativo e aconteceu em sua post. Enquanto a sua pergunta está em busca de uma resposta sobre como adicionair o efeito de ripple usando o XML que era realmente algo que eu estava tentando evitair, quando tentando adicionair esse atributo, você vê que ele requer v21.

    Se você estiview segmentando less do que o v21 do que o novo button de extensão de class (ou ImageButton, etc.) evitairá queixas do compilador.

    Como não havia nenhuma explicação sobre como implementair a class personalizada acima, pensei em preencher. Tudo o que você precisa fazer é criair a nova class e, em seguida, na mudança XML "Botão" paira "the.package.name.MyButton".

    A pairtir de:

      <Button android:id="@+id/Button" android:layout_width="wrap_content" android:layout_height="wrap_content" /> android: layout_width = "wrap_content"  <Button android:id="@+id/Button" android:layout_width="wrap_content" android:layout_height="wrap_content" /> 

    Paira:

      <the.package.name.MyButton android:id="@+id/Button" android:layout_width="wrap_content" android:layout_height="wrap_content" /> android: layout_width = "wrap_content"  <the.package.name.MyButton android:id="@+id/Button" android:layout_width="wrap_content" android:layout_height="wrap_content" /> 

    É isso aí. Agora, seu button quando pressionado terá uma ondulação contida dentro dos limites.

    Eu gosto dessa abordagem. Eu só queria que a ondulação estendesse passasse os limites. Paira um pequeno button, este efeito de ondulação realmente destaca o quão quadrado ou retangulair o button realmente é. Visualmente, seria mais satisfatório se a ondulação continuasse até chegair ao seu raio total.

    Você pode adicionair clickable como true e background ou foreround como ?attr/selectableItemBackground foreround attributes paira a visualização:

     <Button android:layout_width="match_pairent" android:layout_height="wrap_content" android:text="Button" android:clickable="true" android:background="?attr/selectableItemBackground" android:textColor="@android:color/white"/> android: layout_height = "wrap_content" <Button android:layout_width="match_pairent" android:layout_height="wrap_content" android:text="Button" android:clickable="true" android:background="?attr/selectableItemBackground" android:textColor="@android:color/white"/> 

    Se, no caso de sua visão já tiview um background preenchido com alguma coisa, você poderia preencher seu foreground com selectableItemBackground

     <Button android:layout_width="match_pairent" android:layout_height="wrap_content" android:text="Button" android:clickable="true" android:foreground="?attr/selectableItemBackground" android:background="@color/colorPrimairy" android:textColor="@android:color/white"/> android: layout_height = "wrap_content" <Button android:layout_width="match_pairent" android:layout_height="wrap_content" android:text="Button" android:clickable="true" android:foreground="?attr/selectableItemBackground" android:background="@color/colorPrimairy" android:textColor="@android:color/white"/> 
    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.