为了账号安全,请及时绑定邮箱和手机立即绑定

Android中实现类似探探中图片左右滑动切换效果

标签:
Android

偶然之间发现探探的左右滑动的图片挺好玩,试着去做了下,再到后来,看到许多大神也推出了同样仿探探效果的博客,从头到尾阅读下来,写得通俗易懂,基本上没什么问题。于是,实现仿探探效果的想法再次出现在脑海中。那么,还犹豫什么,趁热来一发吧!就这么愉快地决定了。

RecyclerView 是最佳选择!

RecyclerView 是最佳选择!

RecyclerView 是最佳选择!

重要的话讲三遍!!!

究其原因,第一,RecyclerView 是自带 Item View 回收和重用功能的,就不需要我们考虑这个问题了;第二,RecyclerView 的布局方式是通过设置 LayoutManager 来实现的,这样就充分地把布局和 RecyclerView “解耦”开来了。而 LayoutManager 是可以通过自定义的方式来实现的。这恰恰是我们想要的!!!再说一点,这也正是不选用 ListView 的原因之一。


下面,我们就开始动手了。带你见证奇迹的时刻。

1.创建 CardLayoutManager 并继承自 RecyclerView.LayoutManager 。需要我们自己实现 generateDefaultLayoutParams() 方法:

@Overridepublic RecyclerView.LayoutParams generateDefaultLayoutParams() {    return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);}

2.一般情况下,像上面这样写即可。


下面这个方法就是我们的重点了。 onLayoutChildren(final RecyclerView.Recycler recycler, RecyclerView.State state) 方法就是用来实现 Item View 布局的:


@Overridepublic void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {    super.onLayoutChildren(recycler, state);    removeAllViews();    detachAndScrapAttachedViews(recycler);    int itemCount = getItemCount();    if(itemCount>CardConfig.DEFAULT_SHOW_ITEM){        for(int position = CardConfig.DEFAULT_SHOW_ITEM;position>=0;position--){            final View view = recycler.getViewForPosition(position);            addView(view);            measureChildWithMargins(view,0,0);            int widthSpace = getWidth() -getDecoratedMeasuredWidth(view);            int heightSpace = getHeight() - getBottomDecorationHeight(view);            layoutDecoratedWithMargins(view,widthSpace/2,heightSpace/2,widthSpace/2+getDecoratedMeasuredWidth(view),heightSpace/2+getBottomDecorationHeight(view));            if(position == CardConfig.DEFAULT_SHOW_ITEM){
                view.setScaleX(1-(position-1)*CardConfig.DEFAULT_SCALE);                view.setScaleY(1-(position-1)*CardConfig.DEFAULT_SCALE);                view.setTranslationY((position-1)*view.getMeasuredHeight()/CardConfig.DEFAULT_TRANSLATE_Y);            }else if(position>0){
                view.setScaleX(1 - position * CardConfig.DEFAULT_SCALE);                view.setScaleY(1 - position * CardConfig.DEFAULT_SCALE);                view.setTranslationY(position * view.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);            }else{
                view.setOnTouchListener(mOnTouchListener);            }
        }
    }else{        // 当数据源个数小于或等于最大显示数时        for (int position = itemCount - 1; position >= 0; position--) {            final View view = recycler.getViewForPosition(position);            addView(view);            measureChildWithMargins(view, 0, 0);            int widthSpace = getWidth() - getDecoratedMeasuredWidth(view);            int heightSpace = getHeight() - getDecoratedMeasuredHeight(view);            // recyclerview 布局            layoutDecoratedWithMargins(view, widthSpace / 2, heightSpace / 2,                    widthSpace / 2 + getDecoratedMeasuredWidth(view),                    heightSpace / 2 + getDecoratedMeasuredHeight(view));            if (position > 0) {
                view.setScaleX(1 - position * CardConfig.DEFAULT_SCALE);                view.setScaleY(1 - position * CardConfig.DEFAULT_SCALE);                view.setTranslationY(position * view.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);            } else {
                view.setOnTouchListener(mOnTouchListener);            }
        }
    }

}

3.创建onTouchListener

private View.OnTouchListener mOnTouchListener = new View.OnTouchListener() {    @Override    public boolean onTouch(View v, MotionEvent event) {
        RecyclerView.ViewHolder childViewHolder = mRecyclerView.getChildViewHolder(v);        if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {            mItemTouchHelper.startSwipe(childViewHolder);        }        return false;    }
};

4.完整CardLayoutManager代码如下


public class CardLayoutManager extends RecyclerView.LayoutManager {    private RecyclerView mRecyclerView;    private ItemTouchHelper mItemTouchHelper;    public CardLayoutManager(@NonNull RecyclerView recyclerView, @NonNull ItemTouchHelper itemTouchHelper) {        this.mRecyclerView = recyclerView;        this.mItemTouchHelper = itemTouchHelper;    }    @Override    public RecyclerView.LayoutParams generateDefaultLayoutParams() {        return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);    }    @Override    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {        super.onLayoutChildren(recycler, state);        removeAllViews();        detachAndScrapAttachedViews(recycler);        int itemCount = getItemCount();        if(itemCount>CardConfig.DEFAULT_SHOW_ITEM){            for(int position = CardConfig.DEFAULT_SHOW_ITEM;position>=0;position--){                final View view = recycler.getViewForPosition(position);                addView(view);                measureChildWithMargins(view,0,0);                int widthSpace = getWidth() -getDecoratedMeasuredWidth(view);                int heightSpace = getHeight() - getBottomDecorationHeight(view);                layoutDecoratedWithMargins(view,widthSpace/2,heightSpace/2,widthSpace/2+getDecoratedMeasuredWidth(view),heightSpace/2+getBottomDecorationHeight(view));                if(position == CardConfig.DEFAULT_SHOW_ITEM){
                    view.setScaleX(1-(position-1)*CardConfig.DEFAULT_SCALE);                    view.setScaleY(1-(position-1)*CardConfig.DEFAULT_SCALE);                    view.setTranslationY((position-1)*view.getMeasuredHeight()/CardConfig.DEFAULT_TRANSLATE_Y);                }else if(position>0){
                    view.setScaleX(1 - position * CardConfig.DEFAULT_SCALE);                    view.setScaleY(1 - position * CardConfig.DEFAULT_SCALE);                    view.setTranslationY(position * view.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);                }else{
                    view.setOnTouchListener(mOnTouchListener);                }
            }
        }else{            // 当数据源个数小于或等于最大显示数时            for (int position = itemCount - 1; position >= 0; position--) {                final View view = recycler.getViewForPosition(position);                addView(view);                measureChildWithMargins(view, 0, 0);                int widthSpace = getWidth() - getDecoratedMeasuredWidth(view);                int heightSpace = getHeight() - getDecoratedMeasuredHeight(view);                // recyclerview 布局                layoutDecoratedWithMargins(view, widthSpace / 2, heightSpace / 2,                        widthSpace / 2 + getDecoratedMeasuredWidth(view),                        heightSpace / 2 + getDecoratedMeasuredHeight(view));                if (position > 0) {
                    view.setScaleX(1 - position * CardConfig.DEFAULT_SCALE);                    view.setScaleY(1 - position * CardConfig.DEFAULT_SCALE);                    view.setTranslationY(position * view.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);                } else {
                    view.setOnTouchListener(mOnTouchListener);                }
            }
        }

    }    private View.OnTouchListener mOnTouchListener = new View.OnTouchListener() {        @Override        public boolean onTouch(View v, MotionEvent event) {
            RecyclerView.ViewHolder childViewHolder = mRecyclerView.getChildViewHolder(v);            if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {                mItemTouchHelper.startSwipe(childViewHolder);            }            return false;        }
    };}



可以看出,大致的效果已经有了。缺少的就是处理触摸滑动事件了。

5.CardConfig

public class CardConfig {    /**     * 显示可见的卡片数量     */    public static final int DEFAULT_SHOW_ITEM = 3;    /**     * 默认缩放的比例     */    public static final float DEFAULT_SCALE = 0.1f;    /**     * 卡片Y轴偏移量时按照14等分计算     */    public static final int DEFAULT_TRANSLATE_Y = 14;    /**     * 卡片滑动时默认倾斜的角度     */    public static final float DEFAULT_ROTATE_DEGREE = 15f;    /**     * 卡片滑动时不偏左也不偏右     */    public static final int SWIPING_NONE = 1;    /**     * 卡片向左滑动时     */    public static final int SWIPING_LEFT = 1 << 2;    /**     * 卡片向右滑动时     */    public static final int SWIPING_RIGHT = 1 << 3;    /**     * 卡片从左边滑出     */    public static final int SWIPED_LEFT = 1;    /**     * 卡片从右边滑出     */    public static final int SWIPED_RIGHT = 1 << 2;}

6.OnSwipeListener

在看滑动事件的代码之前,我们先定义一个监听器。主要用于监听卡片滑动事件,代码就如下所示,注释也给出来了。应该都看得懂吧:


public interface OnSwipeListener<T> {    /**     * 卡片还在滑动时回调     *     * @param viewHolder 该滑动卡片的viewHolder     * @param ratio      滑动进度的比例     * @param direction  卡片滑动的方向,CardConfig.SWIPING_LEFT 为向左滑,CardConfig.SWIPING_RIGHT 为向右滑,     *                   CardConfig.SWIPING_NONE 为不偏左也不偏右     */    void onSwiping(RecyclerView.ViewHolder viewHolder, float ratio, int direction);    /**     * 卡片完全滑出时回调     *     * @param viewHolder 该滑出卡片的viewHolder     * @param t          该滑出卡片的数据     * @param direction  卡片滑出的方向,CardConfig.SWIPED_LEFT 为左边滑出;CardConfig.SWIPED_RIGHT 为右边滑出     */    void onSwiped(RecyclerView.ViewHolder viewHolder, T t, int direction);    /**     * 所有的卡片全部滑出时回调     */    void onSwipedClear();}

7.CardItemTouchHelperCallback


现在,我们可以回过头来看看卡片滑动了。对于 ItemTouchHelper 来处理 Item View 的触摸滑动事件相必都不陌生吧!

我们暂且命名为 CardItemTouchHelperCallback 。对于 ItemTouchHelper.Callback 而言,需要在 getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) 方法中配置 swipeFlags 和 dragFlags 。


public class CardItemTouchHelperCallback<T> extends ItemTouchHelper.Callback {    private final RecyclerView.Adapter adapter;    private List<T> dataList;    private OnSwipeListener<T> mListener;    public CardItemTouchHelperCallback(@NonNull RecyclerView.Adapter adapter, @NonNull List<T> dataList) {        this.adapter = adapter;        this.dataList = dataList;    }    public CardItemTouchHelperCallback(@NonNull RecyclerView.Adapter adapter, @NonNull List<T> dataList, OnSwipeListener<T> listener) {        this.adapter = adapter;        this.dataList = dataList;        this.mListener = listener;    }    @Override    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {        int dragFlags = 0;        int swipeFlags = 0;        RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();        if (layoutManager instanceof CardLayoutManager) {

            swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;        }        return makeMovementFlags(dragFlags, swipeFlags);    }    @Override    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {        return false;    }    @Override    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {        // 移除之前设置的 onTouchListener, 否则触摸滑动会乱了        viewHolder.itemView.setOnTouchListener(null);        // 删除相对应的数据        int layoutPosition = viewHolder.getLayoutPosition();        T remove = dataList.remove(layoutPosition);        adapter.notifyDataSetChanged();        // 卡片滑出后回调 OnSwipeListener 监听器        if (mListener != null) {            mListener.onSwiped(viewHolder, remove, direction == ItemTouchHelper.LEFT ? CardConfig.SWIPED_LEFT : CardConfig.SWIPED_RIGHT);        }        // 当没有数据时回调 OnSwipeListener 监听器        if (adapter.getItemCount() == 0) {            if (mListener != null) {                mListener.onSwipedClear();            }

        }
    }    public void setOnSwipedListener(OnSwipeListener<T> mListener) {        this.mListener = mListener;    }    @Override    public boolean isItemViewSwipeEnabled() {        return false;    }    @Override    public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,                            float dX, float dY, int actionState, boolean isCurrentlyActive) {        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);        View itemView = viewHolder.itemView;        if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {            // 得到滑动的阀值            float ratio = dX / getThreshold(recyclerView, viewHolder);            // ratio 最大为 1 或 -1            if (ratio > 1) {

                ratio = 1;            } else if (ratio < -1) {

                ratio = -1;            }            // 默认最大的旋转角度为 15 度            itemView.setRotation(ratio * CardConfig.DEFAULT_ROTATE_DEGREE);            int childCount = recyclerView.getChildCount();            // 当数据源个数大于最大显示数时            if (childCount > CardConfig.DEFAULT_SHOW_ITEM) {                for (int position = 1; position < childCount - 1; position++) {                    int index = childCount - position - 1;                    View view = recyclerView.getChildAt(position);                    // 和之前 onLayoutChildren 是一个意思,不过是做相反的动画                    view.setScaleX(1 - index * CardConfig.DEFAULT_SCALE + Math.abs(ratio) * CardConfig.DEFAULT_SCALE);                    view.setScaleY(1 - index * CardConfig.DEFAULT_SCALE + Math.abs(ratio) * CardConfig.DEFAULT_SCALE);                    view.setTranslationY((index - Math.abs(ratio)) * itemView.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);                }

            } else {                // 当数据源个数小于或等于最大显示数时                for (int position = 0; position < childCount - 1; position++) {                    int index = childCount - position - 1;                    View view = recyclerView.getChildAt(position);                    view.setScaleX(1 - index * CardConfig.DEFAULT_SCALE + Math.abs(ratio) * CardConfig.DEFAULT_SCALE);                    view.setScaleY(1 - index * CardConfig.DEFAULT_SCALE + Math.abs(ratio) * CardConfig.DEFAULT_SCALE);                    view.setTranslationY((index - Math.abs(ratio)) * itemView.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);                }

            }            // 回调监听器            if (mListener != null) {                if (ratio != 0) {                    mListener.onSwiping(viewHolder, ratio, ratio < 0 ? CardConfig.SWIPING_LEFT : CardConfig.SWIPING_RIGHT);                } else {                    mListener.onSwiping(viewHolder, ratio, CardConfig.SWIPING_NONE);                }

            }

        }

    }    private float getThreshold(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {        return recyclerView.getWidth() * getSwipeThreshold(viewHolder);    }    @Override    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {        super.clearView(recyclerView, viewHolder);        viewHolder.itemView.setRotation(0f);    }
}

8.在Activity中引用


public class MainActivity extends AppCompatActivity {    private List<Integer> list = new ArrayList<>();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();        initData();    }    private void initView() {        final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);        recyclerView.setItemAnimator(new DefaultItemAnimator());        recyclerView.setAdapter(new MyAdapter());        CardItemTouchHelperCallback cardCallback = new CardItemTouchHelperCallback(recyclerView.getAdapter(), list);        cardCallback.setOnSwipedListener(new OnSwipeListener<Integer>() {            @Override            public void onSwiping(RecyclerView.ViewHolder viewHolder, float ratio, int direction) {
                MyAdapter.MyViewHolder myHolder = (MyAdapter.MyViewHolder) viewHolder;                viewHolder.itemView.setAlpha(1 - Math.abs(ratio) * 0.2f);                if (direction == CardConfig.SWIPING_LEFT) {
                    myHolder.dislikeImageView.setAlpha(Math.abs(ratio));                } else if (direction == CardConfig.SWIPING_RIGHT) {
                    myHolder.likeImageView.setAlpha(Math.abs(ratio));                } else {
                    myHolder.dislikeImageView.setAlpha(0f);                    myHolder.likeImageView.setAlpha(0f);                }
            }            @Override            public void onSwiped(RecyclerView.ViewHolder viewHolder, Integer o, int direction) {
                MyAdapter.MyViewHolder myHolder = (MyAdapter.MyViewHolder) viewHolder;                viewHolder.itemView.setAlpha(1f);                myHolder.dislikeImageView.setAlpha(0f);                myHolder.likeImageView.setAlpha(0f);                Toast.makeText(MainActivity.this, direction == CardConfig.SWIPED_LEFT ? "swiped left" : "swiped right", Toast.LENGTH_SHORT).show();            }            @Override            public void onSwipedClear() {
                Toast.makeText(MainActivity.this, "data clear", Toast.LENGTH_SHORT).show();                recyclerView.postDelayed(new Runnable() {                    @Override                    public void run() {
                        initData();                        recyclerView.getAdapter().notifyDataSetChanged();                    }
                }, 3000L);            }

        });        final ItemTouchHelper touchHelper = new ItemTouchHelper(cardCallback);        final CardLayoutManager cardLayoutManager = new CardLayoutManager(recyclerView, touchHelper);        recyclerView.setLayoutManager(cardLayoutManager);        touchHelper.attachToRecyclerView(recyclerView);    }    private void initData() {        list.add(R.drawable.img_avatar_01);        list.add(R.drawable.img_avatar_02);        list.add(R.drawable.img_avatar_03);        list.add(R.drawable.img_avatar_04);        list.add(R.drawable.img_avatar_05);        list.add(R.drawable.img_avatar_06);        list.add(R.drawable.img_avatar_07);    }    private class MyAdapter extends RecyclerView.Adapter {        @Override        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);            return new MyViewHolder(view);        }        @Override        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            ImageView avatarImageView = ((MyViewHolder) holder).avatarImageView;            avatarImageView.setImageResource(list.get(position));        }        @Override        public int getItemCount() {            return list.size();        }        class MyViewHolder extends RecyclerView.ViewHolder {

            ImageView avatarImageView;            ImageView likeImageView;            ImageView dislikeImageView;            MyViewHolder(View itemView) {                super(itemView);                avatarImageView = (ImageView) itemView.findViewById(R.id.iv_avatar);                likeImageView = (ImageView) itemView.findViewById(R.id.iv_like);                dislikeImageView = (ImageView) itemView.findViewById(R.id.iv_dislike);            }

        }
    }

9.MainActiviy布局文件

<?xml version="1.0" encoding="utf-8"?><LinearLayout 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:orientation="vertical"   >    <android.support.v7.widget.RecyclerView        android:id="@+id/recyclerView"        android:layout_width="match_parent"        android:layout_height="match_parent" /></LinearLayout>

10.item布局

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:layout_width="336dp"    android:layout_height="426dp"    android:background="@drawable/img_card_background"    android:gravity="center"    android:orientation="vertical">    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1">        <com.example.admin.tantanuse.RoundImageView            android:id="@+id/iv_avatar"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:scaleType="centerCrop"            app:radius="7.5dp"            android:class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="@drawable/img_avatar_01" />        <ImageView            android:id="@+id/iv_dislike"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentRight="true"            android:layout_marginRight="15dp"            android:layout_marginTop="15dp"            android:alpha="0"            android:class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="@drawable/img_dislike" />        <ImageView            android:id="@+id/iv_like"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginLeft="15dp"            android:layout_marginTop="15dp"            android:alpha="0"            android:class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="@drawable/img_like" />    </RelativeLayout>    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="100dp"        android:paddingLeft="14dp"        android:paddingTop="15dp">        <TextView            android:id="@+id/tv_name"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:gravity="center"            android:text="小姐姐"            android:textColor="@android:color/black"            android:textSize="16sp" />        <TextView            android:id="@+id/tv_age"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_below="@id/tv_name"            android:layout_marginTop="5dp"            android:background="@drawable/shape_age"            android:gravity="center"            android:text=" 23"            android:textColor="#FFFFFF"            android:textSize="14sp" />        <TextView            android:id="@+id/tv_constellation"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_below="@id/tv_name"            android:layout_marginLeft="4dp"            android:layout_marginTop="5dp"            android:layout_toRightOf="@id/tv_age"            android:background="@drawable/shape_constellation"            android:gravity="center"            android:text="狮子座"            android:textColor="#FFFFFF"            android:textSize="14sp" />        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_below="@id/tv_age"            android:layout_marginTop="5dp"            android:gravity="center"            android:text="IT/互联网"            android:textColor="#cbcbcb" />    </RelativeLayout></LinearLayout>

11.带圆角的ImagView

public class RoundImageView extends ImageView {    private Path mPath;    private RectF mRectF;    private float[] rids = new float[8];    private PaintFlagsDrawFilter paintFlagsDrawFilter;    public RoundImageView(Context context) {        this(context, null);    }    public RoundImageView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public RoundImageView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView);        float mRadius = array.getDimension(R.styleable.RoundImageView_radius, 10);        rids[0] = mRadius;        rids[1] = mRadius;        rids[2] = mRadius;        rids[3] = mRadius;        rids[4] = 0f;        rids[5] = 0f;        rids[6] = 0f;        rids[7] = 0f;        array.recycle();        mPath = new Path();        paintFlagsDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);        setLayerType(View.LAYER_TYPE_HARDWARE, null);    }    @Override    protected void onDraw(Canvas canvas) {        mPath.reset();        mPath.addRoundRect(mRectF, rids, Path.Direction.CW);        canvas.setDrawFilter(paintFlagsDrawFilter);        canvas.save();        canvas.clipPath(mPath);        super.onDraw(canvas);        canvas.restore();    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        mRectF = new RectF(0, 0, w, h);    }
}

12.attrs.XML

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="RoundImageView">        <attr name="radius" format="reference|dimension" />    </declare-styleable></resources>

原文链接:http://www.apkbus.com/blog-896840-65485.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消