2016-10-19 10 views
0

波紋カードビューのリップルホットスポットを設定する方法は?タッチポイントから

Googleは、彼らがそれらの波紋アニメーションをトリガしたタッチポイントから出ていないよう材料設計スタイルのUIにリップルアニメーションを使用した場合、アプリ開発者に指摘を開始しました。

Googleの検索エンジンを使用して、この作業を行う方法を説明した唯一のものは、Lucas RochaのTwoWayViewライブラリの問題に関するコメントでした。幸いなことに、そのコメントは私にとってはうまくいくようなものを作るのに十分なものでした。

彼のつぶやきでButcher氏がヒントしたように、キーはDrawableのsetHotspot()メソッドのようです。 APIレベル21で追加された、これはdrawableに "ホットスポット"を教え、RippleDrawableは明らかにこれを波紋効果の発散点として使用します。 setHotspot()は浮動小数点値のペアを取ります。おそらくOnTouchListener内でsetHotspot()を使用することに注意してください。これは、MotionEventがfloat値のタッチイベントのX/Y位置を報告するためです。

このサンプルアプリケーションでは、次の書籍の更新のために取り組んでいる50ページ以上の章の一環として、RecyclerViewのコンテキストでsetHotspot()を使用する方法を示します。このRecyclerViewは、従来のListViewの基本構造を複製するためにLinearLayoutManagerを使用しています。私の行はCardViewに基づいています:

`` `ユーザーが行に触れた場合は、XML

だから、私はそのホットスポットとしてバックグラウンドへのタッチポイントを伝播します。タッチイベントを消費していないことを示すためにfalseを返すので、必要に応じて残りのイベントハンドラに処理を継続します。

このsetHotspot()呼び出しがなければ、RippleDrawableはデフォルトでドロアブルの中心にあるようです。したがって、リストスタイルのRecyclerViewの行の場合、波紋効果は行の中央から出現します。タッチイベントに関連付けられたsetHotspot()は、エミッタポイントを変更します。

<?xml version="1.0" encoding="utf-8"?> 
 
<android.support.v7.widget.CardView 
 
    xmlns:android="http://schemas.android.com/apk/res/android" 
 
    xmlns:cardview="http://schemas.android.com/apk/res-auto" 
 
    android:layout_width="match_parent" 
 
    android:layout_height="wrap_content" 
 
    android:layout_margin="4dp" 
 
    cardview:cardCornerRadius="4dp"> 
 

 
    <LinearLayout 
 
    android:id="@+id/row_content" 
 
    android:layout_width="match_parent" 
 
    android:layout_height="wrap_content" 
 
    android:orientation="horizontal" 
 
    android:background="?android:attr/selectableItemBackground"> 
 

 
    <!-- other widgets in here --> 
 

 
    </LinearLayout> 
 

 
    </LinearLayout> 
 

 
</android.support.v7.widget.CardView> 
 
``` 
 

 
The LinearLayout that the CardView wraps has ?android:attr/selectableItemBackground as its background, pulling in a theme attribute. If this app runs on API Level 21, that background will be a RippleDrawable. 
 

 
When I set up the row, I attach an OnTouchListener to set the hotspot, but only on API Level 21+ devices (as setHotspot() does not exist before then): 
 

 
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
 
    row.setOnTouchListener(new View.OnTouchListener() { 
 
    @TargetApi(Build.VERSION_CODES.LOLLIPOP) 
 
    @Override 
 
    public boolean onTouch(View v, MotionEvent event) { 
 
     v 
 
     .findViewById(R.id.row_content) 
 
     .getBackground() 
 
     .setHotspot(event.getX(), event.getY()); 
 

 
     return(false); 
 
    } 
 
    }); 
 
}

これは動作するようです。私はそれが正式な正解であるかどうか分かりません。これは、Googleがどのようにこれを実装するのかわからない限りです(setHotspot()のSDKサンプルを検索すると何も表示されません)。特に、バックグラウンドでsetHotspot()を直接呼び出すと、私はmutate()を最初に呼び出すべきでしょうか?)。ですから、一面に約15cmの塩の粒を想像して、この実装で塩分を取ります。

答えて

0

表示アニメーションは、ユーザーが表示するか、 のUI要素のグループを非表示にするとビジュアルな連続性を提供します。 ViewAnimationUtils.createCircularReveal()メソッドを使用すると、 にクリッピングサークルをアニメートしてビューを表示または非表示にすることができます。この効果を使用して、以前に可視表示を非表示にする

View myView = findViewById(R.id.my_view); 

// get the center for the clipping circle 
int cx = myView.getWidth()/2; 
int cy = myView.getHeight()/2; 

// get the final radius for the clipping circle 
float finalRadius = (float) Math.hypot(cx, cy); 

// create the animator for this view (the start radius is zero) 
Animator anim = 
    ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius); 

// make the view visible and start the animation 
myView.setVisibility(View.VISIBLE); 
anim.start(); 

:この効果を使用して、以前に目に見えないビューを明らかに

// previously visible view 
final View myView = findViewById(R.id.my_view); 

// get the center for the clipping circle 
int cx = myView.getWidth()/2; 
int cy = myView.getHeight()/2; 

// get the initial radius for the clipping circle 
float initialRadius = (float) Math.hypot(cx, cy); 

// create the animation (the final radius is zero) 
Animator anim = 
    ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0); 

// make the view invisible when the animation is done 
anim.addListener(new AnimatorListenerAdapter() { 
    @Override 
    public void onAnimationEnd(Animator animation) { 
     super.onAnimationEnd(animation); 
     myView.setVisibility(View.INVISIBLE); 
    } 
}); 

// start the animation 
anim.start(); 
関連する問題