android 实现TextView和imager的倒影效果

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对象,实现倒影图片所在的区域效果

以上就算是完成了,特此记录;

源码下载http://download.csdn.net/download/xiao_yuanjl/10141056

猜你喜欢

转载自blog.csdn.net/xiao_yuanjl/article/details/78645400