Slide Image in RecyclerView
Bài đăng này đã không được cập nhật trong 3 năm
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. Model, data, view, interface
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_width, -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 widthMeasureSpec, int heightMeasureSpec) {
Drawable d = getDrawable();
if (d != null) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = 0;
height = (int) Math.ceil((float) width
* (float) d.getIntrinsicHeight()
/ (float) d.getIntrinsicWidth());
setMeasuredDimension(width, height);
} else {
super.onMeasure(widthMeasureSpec, 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. Adapter
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_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">
<ImageView
android:id="@+id/image_slide"
android:layout_width="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_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:orientation="vertical">
<TextView
android:layout_width="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_width="match_parent"
android:layout_height="@dimen/size_200"/>
<tuananh.com.slideimageinrecyclerview.view.custom.CircleIndicator
android:id="@+id/indicator"
android:layout_width="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>
Image
Tham khảo
Code
All rights reserved