Reputation: 1717
I need to do some like ripple effect of Listview
item background changing. I try to use ObjectAnimator
like this:
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(activity,
R.animator.animator_bkg);
set.setTarget(childLinear);
set.setInterpolator(new AccelerateInterpolator());
set.start();
R.animator.animator_bkg:
<objectAnimator
android:propertyName="backgroundColor"
android:duration="3000"
android:valueFrom="@color/white"
android:valueTo="@color/redTrans"
android:repeatCount="-1"
android:repeatMode="reverse"/>
It fluently changes a background (complete filling), but I need gradual filling of ListView
item like ripple effect after touch the button.
I think, maybe I can use Canvas
with overriding onDraw
, but it's to hard for application and it can be some lags.
Upvotes: 4
Views: 1904
Reputation: 13039
You can do it with a custom view and implement the circular transition in onDraw(), but it's complicated.
You can work around the complexity by using ViewAnimationUtils.createCircularReveal()
on sub view. But the draw back is that it's only for API 21+.
In few words, your root layout of the cell has to be a FrameLayout
or a RelativeLayout
.
When the transition starts, you dynamically add 2 views under your cell with the start and the end color, then transition with the circular reveal between the 2. At the end of the transition, you just remove the 2 sub views to keep the view hierarchy a bit cleaner.
Here is the result :
In code :
Cell layout:
<FrameLayout
android:id="@+id/cell_root"
android:layout_width="match_parent"
android:layout_height="72dp">
<LinearLayout
android:id="@+id/cell_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp"
android:background="#FF00FF">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Title"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is content"
android:textSize="14sp" />
</LinearLayout>
</FrameLayout>
Code that trigger the background transition :
private void changeBackgroundColor() {
final FrameLayout startingColorFrame = new FrameLayout(mCellRoot.getContext());
final FrameLayout endingColorFrame = new FrameLayout(mCellRoot.getContext());
startingColorFrame.setBackground(mCellContent.getBackground());
endingColorFrame.setBackground(mPendingColor);
mCellContent.setBackground(null);
endingColorFrame.setVisibility(View.GONE);
mCellRoot.addView(endingColorFrame, 0, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
mCellRoot.addView(startingColorFrame, 0, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
int finalRadius = (int) Math.sqrt(mCellRoot.getWidth()*mCellRoot.getWidth() + mCellRoot.getHeight()*mCellRoot.getHeight());
final int sourceX = mCellRoot.getWidth() / 3;
final int sourceY = mCellRoot.getHeight() / 2;
// this is API 21 minimum. Add proper checks
final Animator circularReveal = ViewAnimationUtils.createCircularReveal(endingColorFrame, sourceX, sourceY, 0, finalRadius);
endingColorFrame.setVisibility(View.VISIBLE);
circularReveal.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(final Animator animation) {
super.onAnimationEnd(animation);
mStartButton.setEnabled(true);
mCellContent.setBackground(mPendingColor);
mPendingColor = startingColorFrame.getBackground();
mCellRoot.removeView(startingColorFrame);
mCellRoot.removeView(endingColorFrame);
}
});
// customize the animation here
circularReveal.setDuration(800);
circularReveal.setInterpolator(new AccelerateInterpolator());
circularReveal.start();
}
Upvotes: 2