public class

RippleDrawable                                      Added in API level 21

extends  LayerDrawable
java.lang.Object
   ↳ android.graphics.drawable.Drawable
     ↳ android.graphics.drawable.LayerDrawable
       ↳ android.graphics.drawable.RippleDrawable




可以使用系统的默认效果

?android:attr/selectableItemBackground (有界波纹)

?android:attr/selectableItemBackgroundBorderless (无界波纹)



这两个属性对应(在themes_material.xml里)
 <item name="selectableItemBackground">@drawable/item_background_material</item>
 <item name="selectableItemBackgroundBorderless">@drawable/item_background_borderless_material</item>

item_background_borderless_material.xml
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?attr/colorControlHighlight" />



item_background_borderless_material_dark.xml
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/ripple_material_dark" />


item_background_borderless_material_light.xml
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/ripple_material_light" />


item_background_material.xml
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?attr/colorControlHighlight">
    <item android:id="@id/mask">
        <color android:color="@color/white" />
    </item>
</ripple>


item_background_material_dark.xml
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/ripple_material_dark">
  <item android:id="@id/mask">
    <color android:color="@color/white" />
  </item>
</ripple>



item_background_material_light.xml
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/ripple_material_light">
  <item android:id="@id/mask">
    <color android:color="@color/white" />
  </item>
</ripple>

按照上面的格式

 <ImageView
        android:id="@+id/image"
        android:layout_width="400dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:clickable="true"
        android:src="#22354545"
        android:background="@drawable/ripple_drawable"
        android:scaleType="center" />




这个是有边界的
<?xml version="1.0" encoding="utf-8"?>
<ripple
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/accent_dark">
    <item >
    <shape
        android:shape="oval">
        <solid android:color="?android:colorAccent" />
    </shape>
</item>
</ripple>





这是一个无边界的
<?xml version="1.0" encoding="utf-8"?>
<ripple
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/accent_dark">
</ripple>



 ripple里有个radius 属性,表示波纹的中心点就在以View中心点为圆心,radius为半径的圆内
<?xml version="1.0" encoding="utf-8"?>
<ripple
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:radius="100dp"
    android:color="@color/accent_dark">
    <item >
    <shape
        android:shape="oval">
        <solid android:color="?android:colorAccent" />
    </shape>
</item>
</ripple>






练习:

布局文件


<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    >

    <LinearLayout
        android:id="@+id/buttonsContainer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_gravity="center"
        android:padding="@dimen/activity_horizontal_margin"
        android:clipChildren="false"
        android:clipToPadding="false"/>

</FrameLayout>





res/layout/circular_button_layout.xml.xml

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="@dimen/button_size"
    android:layout_height="@dimen/button_size"
    android:background="@drawable/circular_button"
    android:stateListAnimator="@anim/button_elevation"
    android:clickable="true"
    >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/circular_button_ripple_selector"
        android:textAppearance="?android:textAppearanceLarge"
        android:textColor="@color/button_text_selector"
        android:duplicateParentState="true"
        android:gravity="center"
        tools:text="Text"
        tools:textColor="#000"
        />

</FrameLayout>




res/drawable/circular_button.xml

<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <solid android:color="@android:color/white"/>
    <stroke android:width="1dp" android:color="#AAA"/>
</shape>





res/drawable/circular_button_ripple_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?android:colorControlHighlight">
    <item android:id="@android:id/mask" android:drawable="@drawable/circular_button"/>
    <item android:drawable="@drawable/circular_button_selector"/>
</ripple>




res/drawable/circular_button_selector.xml
<?xml version="1.0" encoding="utf-8"?>

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true" android:drawable="@drawable/circular_button_selected"/>
    <item android:drawable="@drawable/circular_button"/>
</selector>


res/drawable/circular_button_selected.xml
<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <solid android:color="@color/theme_accent_color"/>
    <stroke android:width="1dp" android:color="#AAA"/>
</shape>





res/anim/button_elevation.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:state_enabled="true"
        android:state_pressed="true">
        <objectAnimator
            android:duration="@android:integer/config_shortAnimTime"
            android:propertyName="translationZ"
            android:valueFrom="2dip"
            android:valueTo="4dip"
            android:valueType="floatType" />
    </item>
    <item>
        <objectAnimator
            android:duration="@android:integer/config_shortAnimTime"
            android:propertyName="translationZ"
            android:valueFrom="4dip"
            android:valueTo="2dip"
            android:valueType="floatType" />
    </item>
</selector>


/**
 * API 21
 * */
public class RippleDrawableActivity extends AppCompatActivity implements View.OnTouchListener{


	private ViewGroup buttonsContainer;
	private ViewGroup activeButton = null;
	private final int MAX_BUTTONS = 3;

	private class  CircleOutLineProvider extends ViewOutlineProvider{
		@Override
		public void getOutline(View view, Outline outline) {
			outline.setOval(0,0,view.getWidth(),view.getHeight());
		}
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_ripple_drawable);

		this.buttonsContainer = (ViewGroup) findViewById(R.id.buttonsContainer);

		int buttonsSpacing = (int) getResources().getDimension(R.dimen.activity_horizontal_margin);
		int buttonSize = (int) getResources().getDimension(R.dimen.button_size);

		CircleOutLineProvider circleOutLineProvider = new CircleOutLineProvider();
		// Outline circularOutline = new Outline();
		// circularOutline.setOval(0, 0, buttonSize, buttonSize);

		for (int i = 0; i < MAX_BUTTONS; i++) {
			ViewGroup buttonHost = (ViewGroup) getLayoutInflater().inflate(R.layout.circular_button_layout, buttonsContainer, false);
			TextView button = (TextView) buttonHost.getChildAt(0);

			buttonHost.setClipToOutline(true);
			buttonHost.setOutlineProvider(circleOutLineProvider);

			button.setText("Test " + i);

			buttonHost.setOnTouchListener(this);
			buttonsContainer.addView(buttonHost);

			//Add margin between buttons manually
			if (i != MAX_BUTTONS - 1) {
				buttonsContainer.addView(new Space(this), new ViewGroup.LayoutParams(buttonsSpacing, buttonSize));
			}
		}
		selectButton(((ViewGroup) buttonsContainer.getChildAt(0)), false);
	}

	private void selectButton(ViewGroup buttonHost, boolean reveal) {
		selectButton(buttonHost, reveal, buttonHost.getWidth(), buttonHost.getHeight());
	}

	private void selectButton(ViewGroup buttonHost, boolean reveal, int startX, int startY) {
		if (buttonHost == activeButton) {
			return;
		}

		if (activeButton != null) {
			activeButton.setSelected(false);
			activeButton = null;
		}

		activeButton = buttonHost;
		activeButton.setSelected(true);

		View button = activeButton.getChildAt(0);

		if (reveal) {
			//API 21
			ViewAnimationUtils.createCircularReveal(button,
					startX,
					startY,
					0,
					button.getHeight()).start();
		}
	}

	@Override
	public boolean onTouch(View view, MotionEvent motionEvent) {
		switch (motionEvent.getAction()) {
			case MotionEvent.ACTION_DOWN:
				((ViewGroup) view).getChildAt(0).getBackground().setHotspot(motionEvent.getX(), motionEvent.getY());
				break;
			case MotionEvent.ACTION_UP:
				selectButton((ViewGroup) view, true, (int) motionEvent.getX(), (int) motionEvent.getY());
				break;

		}
		return false;
	}
}









参考:http://trickyandroid.com/simple-ripple-reveal-elevation-tutorial/



Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐