Slide Image in RecyclerView
Mục đích của bài viết là hướng dẫn cách tạo 1 slide image trong item của recycler view 1.1. Tạo model Profile Tạo 1 model chứa thông tin Profile : gồm id, name, age, và list image package tuananh.com.slideimageinrecyclerview.model; import java.io.Serializable; import java.util.List; /** * ...
Mục đích của bài viết là hướng dẫn cách tạo 1 slide image trong item của recycler view
1.1. Tạo model Profile
Tạo 1 model chứa thông tin Profile : gồm id, name, age, và list image
package tuananh.com.slideimageinrecyclerview.model; import java.io.Serializable; import java.util.List; /** * Created by framgia on 27/04/2017. */ public class Profile implements Serializable { private int mId; private String mName; private int mAge; private List<String> mImageList; public Profile(int id, String name, int age, List<String> imageList) { mId = id; mName = name; mAge = age; mImageList = imageList; } public int getId() { return mId; } public void setId(int id) { mId = id; } public String getName() { return mName; } public void setName(String name) { mName = name; } public List<String> getImageList() { return mImageList; } public void setImageList(List<String> imageList) { mImageList = imageList; } public int getAge() { return mAge; } public void setAge(int age) { mAge = age; } public String getNameAge() { return String.format("%s, %d", getName(), getAge()); } }
1.2. View custom
1.2.1. CircleIndicator
Vẽ và bắt sự kiện scroll viewpage và vẽ lại vị trí của ảnh tương ứng trong list image
package tuananh.com.slideimageinrecyclerview.view.custom; import android.animation.Animator; import android.animation.AnimatorInflater; import android.annotation.TargetApi; import android.content.Context; import android.content.res.TypedArray; import android.database.DataSetObserver; import android.os.Build; import android.support.annotation.AnimatorRes; import android.support.annotation.DrawableRes; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; import android.view.animation.Interpolator; import android.widget.LinearLayout; import tuananh.com.slideimageinrecyclerview.R; import static android.support.v4.view.ViewPager.OnPageChangeListener; public class CircleIndicator extends LinearLayout { private final static int DEFAULT_INDICATOR_WIDTH = 5; private ViewPager mViewpager; private int mIndicatorMargin = -1; private int mIndicatorWidth = -1; private int mIndicatorHeight = -1; private int mAnimatorResId = R.animator.scale_with_alpha; private int mAnimatorReverseResId = 0; private int mIndicatorBackgroundResId = R.drawable.blur_radius; private int mIndicatorUnselectedBackgroundResId = R.drawable.blur_radius; private Animator mAnimatorOut; private Animator mAnimatorIn; private Animator mImmediateAnimatorOut; private Animator mImmediateAnimatorIn; private int mLastPosition = -1; private final OnPageChangeListener mInternalPageChangeListener = new OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { if (mViewpager.getAdapter() == null || mViewpager.getAdapter().getCount() <= 0) { return; } if (mAnimatorIn.isRunning()) { mAnimatorIn.end(); mAnimatorIn.cancel(); } if (mAnimatorOut.isRunning()) { mAnimatorOut.end(); mAnimatorOut.cancel(); } View currentIndicator; if (mLastPosition >= 0 && (currentIndicator = getChildAt(mLastPosition)) != null) { currentIndicator.setBackgroundResource(mIndicatorUnselectedBackgroundResId); mAnimatorIn.setTarget(currentIndicator); mAnimatorIn.start(); } View selectedIndicator = getChildAt(position); if (selectedIndicator != null) { selectedIndicator.setBackgroundResource(mIndicatorBackgroundResId); mAnimatorOut.setTarget(selectedIndicator); mAnimatorOut.start(); } mLastPosition = position; } @Override public void onPageScrollStateChanged(int state) { } }; private DataSetObserver mInternalDataSetObserver = new DataSetObserver() { @Override public void onChanged() { super.onChanged(); if (mViewpager == null) { return; } int newCount = mViewpager.getAdapter().getCount(); int currentCount = getChildCount(); if (newCount == currentCount) { // No change return; } else if (mLastPosition < newCount) { mLastPosition = mViewpager.getCurrentItem(); } else { mLastPosition = -1; } createIndicators(); } }; public CircleIndicator(Context context) { super(context); init(context, null); } public CircleIndicator(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); } public CircleIndicator(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public CircleIndicator(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(context, attrs); } private void init(Context context, AttributeSet attrs) { handleTypedArray(context, attrs); checkIndicatorConfig(context); } private void handleTypedArray(Context context, AttributeSet attrs) { if (attrs == null) { return; } TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleIndicator); mIndicatorWidth = typedArray.getDimensionPixelSize(R.styleable.CircleIndicator_ci_awidth, -1); mIndicatorHeight = typedArray.getDimensionPixelSize(R.styleable.CircleIndicator_ci_height, -1); mIndicatorMargin = typedArray.getDimensionPixelSize(R.styleable.CircleIndicator_ci_margin, -1); mAnimatorResId = typedArray.getResourceId(R.styleable.CircleIndicator_ci_animator, R.animator.scale_with_alpha); mAnimatorReverseResId = typedArray.getResourceId(R.styleable.CircleIndicator_ci_animator_reverse, 0); mIndicatorBackgroundResId = typedArray.getResourceId(R.styleable.CircleIndicator_ci_drawable, R.drawable.blur_radius); mIndicatorUnselectedBackgroundResId = typedArray.getResourceId(R.styleable.CircleIndicator_ci_drawable_unselected, mIndicatorBackgroundResId); int orientation = typedArray.getInt(R.styleable.CircleIndicator_ci_orientation, -1); setOrientation(orientation == VERTICAL ? VERTICAL : HORIZONTAL); int gravity = typedArray.getInt(R.styleable.CircleIndicator_ci_gravity, -1); setGravity(gravity >= 0 ? gravity : Gravity.CENTER); typedArray.recycle(); } /** * Create and configure Indicator in Java code. */ public void configureIndicator(int indicatorWidth, int indicatorHeight, int indicatorMargin) { configureIndicator(indicatorWidth, indicatorHeight, indicatorMargin, R.animator.scale_with_alpha, 0, R.drawable.blur_radius, R.drawable.blur_radius); } public void configureIndicator(int indicatorWidth, int indicatorHeight, int indicatorMargin, @AnimatorRes int animatorId, @AnimatorRes int animatorReverseId, @DrawableRes int indicatorBackgroundId, @DrawableRes int indicatorUnselectedBackgroundId) { mIndicatorWidth = indicatorWidth; mIndicatorHeight = indicatorHeight; mIndicatorMargin = indicatorMargin; mAnimatorResId = animatorId; mAnimatorReverseResId = animatorReverseId; mIndicatorBackgroundResId = indicatorBackgroundId; mIndicatorUnselectedBackgroundResId = indicatorUnselectedBackgroundId; checkIndicatorConfig(getContext()); } private void checkIndicatorConfig(Context context) { mIndicatorWidth = (mIndicatorWidth < 0) ? dip2px(DEFAULT_INDICATOR_WIDTH) : mIndicatorWidth; mIndicatorHeight = (mIndicatorHeight < 0) ? dip2px(DEFAULT_INDICATOR_WIDTH) : mIndicatorHeight; mIndicatorMargin = (mIndicatorMargin < 0) ? dip2px(DEFAULT_INDICATOR_WIDTH) : mIndicatorMargin; mAnimatorResId = (mAnimatorResId == 0) ? R.animator.scale_with_alpha : mAnimatorResId; mAnimatorOut = createAnimatorOut(context); mImmediateAnimatorOut = createAnimatorOut(context); mImmediateAnimatorOut.setDuration(0); mAnimatorIn = createAnimatorIn(context); mImmediateAnimatorIn = createAnimatorIn(context); mImmediateAnimatorIn.setDuration(0); mIndicatorBackgroundResId = (mIndicatorBackgroundResId == 0) ? R.drawable.blur_radius : mIndicatorBackgroundResId; mIndicatorUnselectedBackgroundResId = (mIndicatorUnselectedBackgroundResId == 0) ? mIndicatorBackgroundResId : mIndicatorUnselectedBackgroundResId; } private Animator createAnimatorOut(Context context) { return AnimatorInflater.loadAnimator(context, mAnimatorResId); } private Animator createAnimatorIn(Context context) { Animator animatorIn; if (mAnimatorReverseResId == 0) { animatorIn = AnimatorInflater.loadAnimator(context, mAnimatorResId); animatorIn.setInterpolator(new ReverseInterpolator()); } else { animatorIn = AnimatorInflater.loadAnimator(context, mAnimatorReverseResId); } return animatorIn; } public void setViewPager(ViewPager viewPager) { mViewpager = viewPager; if (mViewpager != null && mViewpager.getAdapter() != null) { mLastPosition = -1; createIndicators(); mViewpager.removeOnPageChangeListener(mInternalPageChangeListener); mViewpager.addOnPageChangeListener(mInternalPageChangeListener); mInternalPageChangeListener.onPageSelected(mViewpager.getCurrentItem()); } } public DataSetObserver getDataSetObserver() { return mInternalDataSetObserver; } /** * @deprecated User ViewPager addOnPageChangeListener */ @Deprecated public void setOnPageChangeListener(OnPageChangeListener onPageChangeListener) { if (mViewpager == null) { throw new NullPointerException("can not find Viewpager , setViewPager first"); } mViewpager.removeOnPageChangeListener(onPageChangeListener); mViewpager.addOnPageChangeListener(onPageChangeListener); } private void createIndicators() { removeAllViews(); int count = mViewpager.getAdapter().getCount(); if (count <= 0) { return; } int currentItem = mViewpager.getCurrentItem(); int orientation = getOrientation(); for (int i = 0; i < count; i++) { if (currentItem == i) { addIndicator(orientation, mIndicatorBackgroundResId, mImmediateAnimatorOut); } else { addIndicator(orientation, mIndicatorUnselectedBackgroundResId, mImmediateAnimatorIn); } } } private void addIndicator(int orientation, @DrawableRes int backgroundDrawableId, Animator animator) { if (animator.isRunning()) { animator.end(); animator.cancel(); } View Indicator = new View(getContext()); Indicator.setBackgroundResource(backgroundDrawableId); addView(Indicator, mIndicatorWidth, mIndicatorHeight); LayoutParams lp = (LayoutParams) Indicator.getLayoutParams(); if (orientation == HORIZONTAL) { lp.leftMargin = mIndicatorMargin; lp.rightMargin = mIndicatorMargin; } else { lp.topMargin = mIndicatorMargin; lp.bottomMargin = mIndicatorMargin; } Indicator.setLayoutParams(lp); animator.setTarget(Indicator); animator.start(); } public int dip2px(float dpValue) { final float scale = getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } private class ReverseInterpolator implements Interpolator { @Override public float getInterpolation(float value) { return Math.abs(1.0f - value); } } }
1.2.2 ResizableImageView
Resize Image theo chiều rộng mà ko vỡ ảnh
package tuananh.com.slideimageinrecyclerview.view.custom; import android.content.Context; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; /** * Created by TuanAnh on 4/28/2017. */ public class ResizableImageView extends ImageView { public ResizableImageView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int awidthMeasureSpec, int heightMeasureSpec) { Drawable d = getDrawable(); if (d != null) { int awidth = MeasureSpec.getSize(awidthMeasureSpec); int height = 0; height = (int) Math.ceil((float) awidth * (float) d.getIntrinsicHeight() / (float) d.getIntrinsicWidth()); setMeasuredDimension(awidth, height); } else { super.onMeasure(awidthMeasureSpec, heightMeasureSpec); } } }
1.3. Tạo class create data
Khởi tạo list profile cho ứng dụng
package tuananh.com.slideimageinrecyclerview; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import tuananh.com.slideimageinrecyclerview.model.Profile; /** * Created by framgia on 27/04/2017. */ public class CreateData { public static List<Profile> createProfile() { List<Profile> profileList = new ArrayList<>(); profileList.add(create(1, "Đào", 22, Arrays.asList( "http://imageshack.com/a/img922/986/1C5zeO.jpg", "http://imageshack.com/a/img924/224/taTtUg.jpg", "http://imageshack.com/a/img923/1333/cnHzDa.jpg", "http://imageshack.com/a/img922/9823/TpA14D.jpg", "http://imageshack.com/a/img924/4017/f9pqLq.jpg", "http://imageshack.com/a/img922/8958/4KAmdD.jpg", "http://imageshack.com/a/img923/8135/nyfIov.jpg"))); profileList.add(create(2, "Đào", 22, Arrays.asList( "http://imageshack.com/a/img923/2374/jBIAqT.jpg", "http://imageshack.com/a/img923/9599/ulegwM.jpg", "http://imageshack.com/a/img923/7016/HzEvo8.jpg", "http://imageshack.com/a/img922/1641/emfvPy.jpg", "http://imageshack.com/a/img923/116/yfyetV.jpg", "http://imageshack.com/a/img924/4846/zveut5.jpg", "http://imageshack.com/a/img923/472/SB341D.jpg", "http://imageshack.com/a/img924/4350/5ghok1.jpg"))); profileList.add(create(3, "Đào", 22, Arrays.asList( "http://imageshack.com/a/img923/3835/q79WKE.jpg", "http://imageshack.com/a/img922/3615/sNKPpV.jpg", "http://imageshack.com/a/img924/7272/UXID41.jpg", "http://imageshack.com/a/img923/1332/sTx6qw.jpg", "http://imageshack.com/a/img923/3338/v0hyg5.jpg", "http://imageshack.com/a/img922/8435/puIYQa.jpg"))); profileList.add(create(4, "Đào", 22, Arrays.asList( "http://imageshack.com/a/img922/3390/GXOW9e.jpg", "http://imageshack.com/a/img922/8017/Qnxgbw.jpg"))); profileList.add(create(5, "Đào", 22, Arrays.asList( "http://imageshack.com/a/img924/331/ujExV6.jpg", "http://imageshack.com/a/img923/9503/qgUaHN.jpg", "http://imageshack.com/a/img924/5319/RNBJQp.jpg", "http://imageshack.com/a/img923/3299/nWdFeZ.jpg", "http://imageshack.com/a/img922/461/iIGnvU.jpg", "http://imageshack.com/a/img922/3748/XvWQPz.jpg", "http://imageshack.com/a/img922/2177/gm9ddy.jpg", "http://imageshack.com/a/img924/7344/JBqVbQ.jpg"))); profileList.add(create(6, "Đào", 22, Arrays.asList( "http://imageshack.com/a/img924/6515/JiylGo.jpg", "http://imageshack.com/a/img924/6537/AfNnra.jpg", "http://imageshack.com/a/img924/802/rBCWs3.jpg", "http://imageshack.com/a/img923/9322/bO0hYw.jpg", "http://imageshack.com/a/img923/7392/kyiKsh.jpg"))); profileList.add(create(7, "Đào", 22, Arrays.asList( "http://imageshack.com/a/img924/9423/E8Xxky.jpg", "http://imageshack.com/a/img922/8366/7TVQZk.jpg", "http://imageshack.com/a/img922/8117/3OJydD.jpg"))); profileList.add(create(8, "Đào", 22, Arrays.asList( "http://imageshack.com/a/img923/6430/OK2kfH.jpg", "http://imageshack.com/a/img924/8688/j6RaJz.jpg", "http://imageshack.com/a/img924/7714/LWTaxv.jpg", "http://imageshack.com/a/img922/64/u9LXlR.jpg"))); return profileList; } public static Profile create(int id, String name, int age, List<String> imageList) { return new Profile(id, name, age, imageList); } }
1.4. ViewBindingAdapter
Function loadImage() để vẽ ảnh bằng picasso với link url đc truyền vào
package tuananh.com.slideimageinrecyclerview.view.binding; import android.databinding.BindingAdapter; import android.widget.ImageView; import com.squareup.picasso.Picasso; import tuananh.com.slideimageinrecyclerview.R; /** * Created by framgia on 27/04/2017. */ public class ViewBindingAdapter { @BindingAdapter("imageUrl") public static void loadImage(ImageView imageView, String url) { Picasso.with(imageView.getContext()) .load(url) .placeholder(R.drawable.image_default) .into(imageView); } }
1.5. Interface OnClickShowImageListener
package tuananh.com.slideimageinrecyclerview.listener; import tuananh.com.slideimageinrecyclerview.model.Profile; /** * Created by TuanAnh on 4/28/2017. */ public interface OnClickShowImageListener { void onClickShowImage(Profile profile, int positionImage); }
2.1 SlideImageAdapter
2.1.1. SlideImageAdapter
Tạo Adapter cho slide image là SlideImageAdapter Hàm khởi tạo cần truyền profile và listener onClickShowImageListener ( mục đích là bắt sự kiện OnClickListener vào ảnh để sang trang show full image) public SlideImageAdapter(Context context, Profile profile, OnClickShowImageListener onClickShowImageListener) { }
package tuananh.com.slideimageinrecyclerview.view.adapter; import android.content.Context; import android.databinding.DataBindingUtil; import android.support.v4.view.PagerAdapter; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import java.util.List; import tuananh.com.slideimageinrecyclerview.R; import tuananh.com.slideimageinrecyclerview.databinding.FragmentSlideProfileBinding; import tuananh.com.slideimageinrecyclerview.listener.OnClickShowImageListener; import tuananh.com.slideimageinrecyclerview.model.Profile; /** * Created by framgia on 27/04/2017. */ public class SlideImageAdapter extends PagerAdapter { private Context mContext; private List<String> mImageList; private LayoutInflater mLayoutInflater; private Profile mProfile; private OnClickShowImageListener mOnClickShowImageListener; public SlideImageAdapter(Context context, Profile profile, OnClickShowImageListener onClickShowImageListener) { mContext = context; mProfile = profile; mImageList = profile.getImageList(); mOnClickShowImageListener = onClickShowImageListener; mLayoutInflater = LayoutInflater.from(context); } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } @Override public int getCount() { return mImageList == null ? 0 : mImageList.size(); } @Override public Object instantiateItem(ViewGroup container, final int position) { FragmentSlideProfileBinding binding = DataBindingUtil.inflate(mLayoutInflater, R.layout.fragment_slide_profile, container, false); binding.getRoot().setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mOnClickShowImageListener != null) { mOnClickShowImageListener.onClickShowImage(mProfile, position); } } }); binding.setUrl(mImageList.get(position)); binding.setPosition(position); binding.getRoot().setTag(position); container.addView(binding.getRoot(), 0); return binding.getRoot(); } @Override public boolean isViewFromObject(View view, Object object) { return view.equals(object); } }
2.1.2. Layout
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="position" type="int"/> <variable name="url" type="String"/> </data> <FrameLayout android:layout_awidth="match_parent" android:layout_height="match_parent" android:background="@android:color/white"> <ImageView android:id="@+id/image_slide" android:layout_awidth="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" app:imageUrl="@{url}"/> </FrameLayout> </layout>
2.2. ProfileAdapter
2.2.1. Tạo adapter ProfileAdapter cho reycerview
Function public void bind(Profile profile) {}
- mBinding.setVariable(BR.viewModel, profile); -> truyền data và trong layout
- SlideImageAdapter slideImageAdapter = new SlideImageAdapter(mContext, profile, mOnClickShowImageListener); -> khởi tạo slideImageAdapter cho viewpager trong mỗi item của recyclerview
- mBinding.slideImageViewPager.setAdapter(slideImageAdapter); -> truyền adapter vào viewpager
- mBinding.slideImageViewPager.setOffscreenPageLimit(MAX_SIZE_IMAGE_LOAD); -> load tối đa MAX_SIZE_IMAGE_LOAD ảnh ban đầu
- mBinding.indicator.setViewPager(mBinding.slideImageViewPager); -> truyền viewpager vào CircleIndicator để bắt sự kiện scroll viewpager
package tuananh.com.slideimageinrecyclerview.view.adapter; import android.content.Context; import android.databinding.DataBindingUtil; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.ViewGroup; import java.util.List; import tuananh.com.slideimageinrecyclerview.BR; import tuananh.com.slideimageinrecyclerview.R; import tuananh.com.slideimageinrecyclerview.databinding.ItemRecyclerProfileBinding; import tuananh.com.slideimageinrecyclerview.listener.OnClickShowImageListener; import tuananh.com.slideimageinrecyclerview.model.Profile; /** * Created by TuanAnh on 4/26/2017. */ public class ProfileAdapter extends RecyclerView.Adapter<ProfileAdapter.ProfileViewHolder> { private static final int MAX_SIZE_IMAGE_LOAD = 8; private Context mContext; private LayoutInflater mLayoutInflater; private List<Profile> mProfileList; private OnClickShowImageListener mOnClickShowImageListener; public ProfileAdapter(Context context, List<Profile> profileList, OnClickShowImageListener onClickShowImageListener) { mContext = context; mProfileList = profileList; mOnClickShowImageListener = onClickShowImageListener; mLayoutInflater = LayoutInflater.from(context); } @Override public ProfileViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { ItemRecyclerProfileBinding binding = DataBindingUtil.inflate(mLayoutInflater, R.layout.item_recycler_profile, parent, false); return new ProfileViewHolder(binding); } @Override public void onBindViewHolder(ProfileViewHolder holder, int position) { Profile profile = mProfileList.get(position); holder.bind(profile); } @Override public int getItemCount() { return mProfileList == null ? 0 : mProfileList.size(); } public class ProfileViewHolder extends RecyclerView.ViewHolder { private ItemRecyclerProfileBinding mBinding; public ProfileViewHolder(ItemRecyclerProfileBinding binding) { super(binding.getRoot()); mBinding = binding; } public void bind(Profile profile) { mBinding.setVariable(BR.viewModel, profile); SlideImageAdapter slideImageAdapter = new SlideImageAdapter(mContext, profile, mOnClickShowImageListener); mBinding.sliderImageViewPager.setAdapter(slideImageAdapter); mBinding.sliderImageViewPager.setOffscreenPageLimit(MAX_SIZE_IMAGE_LOAD); mBinding.indicator.setViewPager(mBinding.sliderImageViewPager); mBinding.executePendingBindings(); } } }
2.2.2. Layout
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="viewModel" type="tuananh.com.slideimageinrecyclerview.model.Profile"/> </data> <LinearLayout android:layout_awidth="match_parent" android:layout_height="wrap_content" android:background="@android:color/white" android:orientation="vertical"> <TextView android:layout_awidth="match_parent" android:layout_height="wrap_content" android:layout_margin="@dimen/margin_padding_10" android:layout_marginLeft="@dimen/margin_padding_20" android:drawableLeft="@drawable/img_dots" android:drawablePadding="@dimen/margin_padding_10" android:text="@{viewModel.nameAge}" android:textSize="@dimen/text_size_14" android:textStyle="bold"/> <android.support.v4.view.ViewPager android:id="@+id/slide_image_view_pager" android:layout_awidth="match_parent" android:layout_height="@dimen/size_200"/> <tuananh.com.slideimageinrecyclerview.view.custom.CircleIndicator android:id="@+id/indicator" android:layout_awidth="match_parent" android:layout_height="@dimen/size_30" android:layout_gravity="bottom" app:ci_drawable="@drawable/black_radius" app:ci_drawable_unselected="@drawable/blur_radius"/> </LinearLayout> </layout>