android 实现TextView和imager的倒影效果
不多说了,先上张效果图;
1.首先第一步自定义InvertedImagelayout;
public class InvertedImageLayout extends FrameLayout {
private static final int MIRROR_HEIGHT = 1;// 镜像的默认高度,单位是dp
private static final int MIRROR_MARGIN = 1;// 镜像与子控件的高度
private int mMirrorHeight;
private int mMirrorMargin;
private Bitmap mMirrorBitmap;
private Paint mPaint;
private Canvas mCanvas;
private boolean mShowMirror = false;
public InvertedImageLayout(Context context) {
super(context);
InitView();
}
public InvertedImageLayout(Context context, AttributeSet attrs) {
super(context, attrs);
InitView();
}
public InvertedImageLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
InitView();
}
private void InitView() {
//设置镜像的默认高度
mMirrorHeight = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, MIRROR_HEIGHT, getResources().getDisplayMetrics());
mMirrorMargin = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, MIRROR_MARGIN, getResources().getDisplayMetrics());
//设置抗锯齿,如果不设置,加载位图的时候可能会出现锯齿状的边界;
mPaint = new Paint();
mPaint.setAntiAlias(true);
}
//设置是否显示倒影
public void setShowMirror(boolean v) {
mShowMirror = v;
//重新layout
requestLayout();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取子view的数量
if (getChildCount() <= 0) {
return;
}
//通过调取setShowMirror()设置;
if (!mShowMirror) {
return;
}
//测量子view的宽高
int child_height = getChildAt(0).getMeasuredHeight();
child_height += mMirrorHeight + mMirrorMargin;
setMeasuredDimension(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(child_height, MeasureSpec.EXACTLY));
if (mMirrorBitmap != null && !mMirrorBitmap.isRecycled()) {
if (mMirrorBitmap.getHeight() != child_height) {
mMirrorBitmap.recycle();
mMirrorBitmap = null;
}
}
//创建bitmap
if (mMirrorBitmap == null) {
mMirrorBitmap = Bitmap.createBitmap(getMeasuredWidth(), mMirrorHeight,
Config.ARGB_8888);
mCanvas = new Canvas(mMirrorBitmap);
}
}
//设置倒影的高度
public void setMirrorHeight(int height) {
if (height < 30) {
throw new IllegalArgumentException("mirror height is to small");
}
mMirrorHeight = height;
requestLayout();
}
@Override
protected void dispatchDraw(Canvas canvas) {
try {
super.dispatchDraw(canvas);
if (!mShowMirror) {
return;
}
if (getChildCount() == 0) {
return;
}
if (mMirrorBitmap == null) {
return;
}
drawMirrorBitmap(canvas);
} catch (Exception e) {
e.printStackTrace();
}
}
private void drawMirrorBitmap(Canvas canvas) {
View child = getChildAt(0);
//开始绘制
mCanvas.save();
Matrix m = new Matrix();
m.preTranslate(0f, child.getMeasuredHeight() * 1.0f);
//对当前view进行翻转
m.preScale(1f, -1f);
mCanvas.setMatrix(m);
//进行绘制
child.draw(mCanvas);
//绘制完成
mCanvas.restore();
//进行渲染,可设置自己想要的进行渲染效果
LinearGradient linear = new LinearGradient(0, 0, 0, mMirrorBitmap.getHeight(), 0xA2ffffff, 0x00ffffff, TileMode.CLAMP);
Paint paint = new Paint();
//设置着色器,用来给图像着色的,绘制出渐变效果
paint.setShader(linear);
//设置图形显示方式
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
mCanvas.drawRect(0, 0, mMirrorBitmap.getWidth(), mMirrorBitmap.getHeight(), paint);
//绘制该位图
canvas.drawBitmap(mMirrorBitmap, child.getX(), child.getMeasuredHeight()
+ mMirrorMargin, mPaint);
}
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
//只允许添加一个view
if (getChildCount() > 0) {
throw new IllegalStateException(
"MirrorLayout can host only one direct child");
}
super.addView(child, index, params);
}
@Override
protected void onDetachedFromWindow() {
//当view和window分离,获取当前所有view,删除;
if (getChildCount() != 0) {
removeAllViews();
}
mCanvas = null;
mPaint = null;
super.onDetachedFromWindow();
//回收bitmap
if (mMirrorBitmap != null && !mMirrorBitmap.isRecycled()) {
mMirrorBitmap.recycle();
mMirrorBitmap = null;
}
}
}
2.在来看看xml怎么写的,直接引用已经定义好的view;
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary"
>
<com.personal.view.InvertedImageLayout
android:id="@+id/id_inverted_image_layout"
android:layout_width="match_parent"
android:layout_height="120dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true">
<!-- 也可以直接拖拽ImageView和TextView控件 -->
</com.personal.view.InvertedImageLayout>
</RelativeLayout>
以上完成了吗?NO,并没有,我们需要在MainActivity去进行设置,下面我们来看具体设置;
public class MainActivity extends Activity {
private ImageView imager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InvertedImageLayout mInertedImageView = (InvertedImageLayout) findViewById(R.id.id_inverted_image_layout);
imager=new ImageView(this);
imager.setImageResource(R.drawable.imag_ic);
mInertedImageView.addView(imager);
//也可以设置TextView的效果
/* TextView textview = new TextView(this);
textview.setText("Inverted image layout");
mInertedImageView.addView(textview);*/
//下面这两个调用很重要,设置倒影的高度
mInertedImageView.setMirrorHeight(400);
//是否设置倒影;
mInertedImageView.setShowMirror(true);
}
}
1.利用Matrix矩阵来实现图片的旋转。
2.用刚创建的位图创建一个画布
3.把原始图片和倒影图片添加到画布上去
4.创建线性渐变LinearGradient对象,实现倒影图片所在的区域效果
以上就算是完成了,特此记录;