From 821c2c284333f45cdd16df868fcd5a670c2fc88e Mon Sep 17 00:00:00 2001 From: Mervel999 Date: Wed, 26 Jan 2022 15:11:24 +0530 Subject: [PATCH] Refactor code (Make comments looks more cleaner.) --- .../CarouselLayoutManager.kt | 150 ++++++++++-------- .../CarouselRecyclerview.kt | 37 ++--- .../view/ReflectionImageView.kt | 9 +- .../view/ReflectionViewContainer.kt | 59 +++++-- 4 files changed, 143 insertions(+), 112 deletions(-) diff --git a/carouselrecyclerview/src/main/java/com/jackandphantom/carouselrecyclerview/CarouselLayoutManager.kt b/carouselrecyclerview/src/main/java/com/jackandphantom/carouselrecyclerview/CarouselLayoutManager.kt index 4539173..6041c7b 100644 --- a/carouselrecyclerview/src/main/java/com/jackandphantom/carouselrecyclerview/CarouselLayoutManager.kt +++ b/carouselrecyclerview/src/main/java/com/jackandphantom/carouselrecyclerview/CarouselLayoutManager.kt @@ -15,8 +15,8 @@ import kotlin.math.roundToInt import kotlin.math.sqrt class CarouselLayoutManager constructor( - isLoop: Boolean, isItem3D: Boolean, ratio: Float, flat: Boolean, alpha: Boolean) - : RecyclerView.LayoutManager() { + isLoop: Boolean, isItem3D: Boolean, ratio: Float, flat: Boolean, alpha: Boolean +) : RecyclerView.LayoutManager() { /** * We are supposing that all the items in recyclerview will have same size @@ -30,10 +30,10 @@ class CarouselLayoutManager constructor( /** Initially position of an item (x coordinates) */ private var mStartX = 0 - /** items Sliding offset */ + /** Items Sliding offset */ private var mOffsetAll = 0 - /** interval ratio is how much portion of a view will show */ + /** Interval ratio is how much portion of a view will show */ private var intervalRatio = 0.5f /** Cached all required items in rect object (left, top, right, bottom) */ @@ -42,8 +42,8 @@ class CarouselLayoutManager constructor( /** Cache those items which are currently attached to the screen */ private val mHasAttachedItems = SparseBooleanArray() - /** animator animate the items in layout manager */ - private var animator:ValueAnimator?= null + /** Animator animate the items in layout manager */ + private var animator: ValueAnimator? = null /** Store recycler so that we can use it in [scrollToPosition]*/ private lateinit var recycler: RecyclerView.Recycler @@ -51,22 +51,22 @@ class CarouselLayoutManager constructor( /** Store state so that we use in scrolling [scrollToPosition] */ private lateinit var state: RecyclerView.State - /** set infinite loop of items in the layout manager if true */ + /** Set infinite loop of items in the layout manager if true */ private var mInfinite = false - /** set tilt of items in layout manager if true */ + /** Set tilt of items in layout manager if true */ private var is3DItem = false - /** set flat each item if true */ + /** Set flat each item if true */ private var isFlat = false - /** set alpha based on the position of items in layout manager if true */ + /** Set alpha based on the position of items in layout manager if true */ private var isAlpha = false - /** interface for the selected item or middle item in the layout manager */ + /** Interface for the selected item or middle item in the layout manager */ private var mSelectedListener: OnSelected? = null - /** selected position of layout manager (center item)*/ + /** Selected position of layout manager (center item)*/ private var selectedPosition: Int = 0 /** Previous item which was in center in layout manager */ @@ -75,7 +75,7 @@ class CarouselLayoutManager constructor( /** Use for restore scrolling in recyclerview at the time of orientation change*/ private var isOrientationChange = false - /** set to enable/disable scrolling in recyclerview */ + /** Set to enable/disable scrolling in recyclerview */ private var isScrollingEnabled = true /** Initialize all the attribute from the constructor and also apply some conditions */ @@ -89,10 +89,10 @@ class CarouselLayoutManager constructor( } companion object { - /**Item moves to right */ + /** Item moves to right */ private const val SCROLL_TO_RIGHT = 1 - /**Items moves to left */ + /** Items moves to left */ private const val SCROLL_TO_LEFT = 2 /** @@ -124,7 +124,7 @@ class CarouselLayoutManager constructor( if (state == null || recycler == null) return - /** check item count and pre layout state of the layout manager*/ + /** Check item count and pre layout state of the layout manager **/ if (state.itemCount <= 0 || state.isPreLayout) { mOffsetAll = 0 return @@ -143,8 +143,10 @@ class CarouselLayoutManager constructor( var offset = mStartX - //Start from the center of the recyclerview - //Save only specific item position + /** + * Start from the center of the recyclerview + * Save only specific item position + */ var i = 0 while (i < itemCount && i < MAX_RECT_COUNT) { var frame = mAllItemsFrames[i] @@ -171,9 +173,10 @@ class CarouselLayoutManager constructor( this.state = state } - /** Method tell recyclerview that layout manager will act on horizontally scroll + /** + * Method tell recyclerview that layout manager will act on horizontally scroll * @return return boolean value to tell recyclerview for scroll handling with horizontal direction - * */ + */ override fun canScrollHorizontally(): Boolean { return isScrollingEnabled @@ -198,13 +201,13 @@ class CarouselLayoutManager constructor( var travel = dx - if (!mInfinite) { - if (dx + mOffsetAll < 0) { - travel = - mOffsetAll - }else if (dx + mOffsetAll > maxOffset()) { - travel = (maxOffset() - mOffsetAll) - } - } + if (!mInfinite) { + if (dx + mOffsetAll < 0) { + travel = -mOffsetAll + } else if (dx + mOffsetAll > maxOffset()) { + travel = (maxOffset() - mOffsetAll) + } + } mOffsetAll += travel layoutItems(recycler, state, if (dx > 0) SCROLL_TO_LEFT else SCROLL_TO_RIGHT) return travel @@ -222,7 +225,7 @@ class CarouselLayoutManager constructor( ) { if (state.isPreLayout) return - //calculate current display area for showing views + /** Calculate current display area for showing views */ val displayFrames = Rect( mOffsetAll, 0, @@ -236,18 +239,18 @@ class CarouselLayoutManager constructor( //get position from tag class define later val tag = checkTAG(child.tag) tag!!.pos - }else { + } else { getPosition(child) } val rect = getFrame(position) - //Now check item is in the display area, if not recycle that item + /** Now check item is in the display area, if not recycle that item */ if (!Rect.intersects(displayFrames, rect)) { removeAndRecycleView(child, recycler) mHasAttachedItems.delete(position) - }else { - //Shift the item which has still in the screen + } else { + /** Shift the item which has still in the screen */ layoutItem(child, rect) mHasAttachedItems.put(position, true) } @@ -261,32 +264,35 @@ class CarouselLayoutManager constructor( if (!mInfinite) { if (min < 0) min = 0 - if (max > itemCount ) max = itemCount + if (max > itemCount) max = itemCount } for (index in min until max) { val rect = getFrame(index) - //layout items area of a view if it's first inside the display area - // and also not already on the screen - if (Rect.intersects(displayFrames, rect) && !mHasAttachedItems.get( - index - )) { - var actualPos = index % itemCount - if (actualPos < 0) actualPos += itemCount - - val scrap = recycler.getViewForPosition(actualPos) - checkTAG(scrap.tag) - scrap.tag = TAG(index) - measureChildWithMargins(scrap, 0, 0) - - if (scrollToDirection == SCROLL_TO_RIGHT) { - addView(scrap, 0) - } else addView(scrap) - - layoutItem(scrap, rect) - mHasAttachedItems.put(index, true) - } - } + /** + * Layout items area of a view if it's first inside the display area + * and also not already on the screen + **/ + if (Rect.intersects(displayFrames, rect) && !mHasAttachedItems.get( + index + ) + ) { + var actualPos = index % itemCount + if (actualPos < 0) actualPos += itemCount + + val scrap = recycler.getViewForPosition(actualPos) + checkTAG(scrap.tag) + scrap.tag = TAG(index) + measureChildWithMargins(scrap, 0, 0) + + if (scrollToDirection == SCROLL_TO_RIGHT) { + addView(scrap, 0) + } else addView(scrap) + + layoutItem(scrap, rect) + mHasAttachedItems.put(index, true) + } + } } @@ -320,12 +326,13 @@ class CarouselLayoutManager constructor( * tilt others views based on the drawing order */ private fun itemRotate(child: View, frame: Rect) { - val itemCenter = (frame.left + frame.right - 2*mOffsetAll) / 2f - var value = (itemCenter - (mStartX + mItemDecoratedWidth / 2f)) * 1f / (itemCount*getIntervalDistance()) + val itemCenter = (frame.left + frame.right - 2 * mOffsetAll) / 2f + var value = + (itemCenter - (mStartX + mItemDecoratedWidth / 2f)) * 1f / (itemCount * getIntervalDistance()) value = sqrt(abs(value).toDouble()).toFloat() val symbol = if (itemCenter > mStartX + mItemDecoratedWidth / 2f) (-1).toFloat() else 1.toFloat() - child.rotationY = symbol * 50* abs(value) + child.rotationY = symbol * 50 * abs(value) } @@ -372,7 +379,7 @@ class CarouselLayoutManager constructor( val direction = if (from < to) SCROLL_TO_LEFT else SCROLL_TO_RIGHT animator = ValueAnimator.ofFloat(from * 1.0f, to * 1.0f) - animator?.duration= 500 + animator?.duration = 500 animator?.interpolator = DecelerateInterpolator() animator?.addUpdateListener { animation -> @@ -411,7 +418,8 @@ class CarouselLayoutManager constructor( return } mOffsetAll = calculatePositionOffset(position) - layoutItems(recycler, + layoutItems( + recycler, state, if (position > selectedPosition) SCROLL_TO_LEFT else SCROLL_TO_RIGHT @@ -432,7 +440,7 @@ class CarouselLayoutManager constructor( position: Int ) { //Loop does not support for smooth scrolling - if (mInfinite||!this::recycler.isInitialized || !this::state.isInitialized) return + if (mInfinite || !this::recycler.isInitialized || !this::state.isInitialized) return val finalOffset = calculatePositionOffset(position) startScroll(mOffsetAll, finalOffset) } @@ -464,7 +472,7 @@ class CarouselLayoutManager constructor( if (child!!.tag != null) { val tag = checkTAG(child.tag) if (tag != null) - return tag.pos + return tag.pos } return getPosition(child) } @@ -476,10 +484,10 @@ class CarouselLayoutManager constructor( return if (tag != null) { if (tag is TAG) { tag as TAG - }else { + } else { throw IllegalArgumentException("You should use the set tag with the position") } - }else { + } else { null } @@ -548,8 +556,10 @@ class CarouselLayoutManager constructor( selectedPosition = ((mOffsetAll / getIntervalDistance()).toFloat()).roundToInt() if (selectedPosition < 0) selectedPosition += itemCount selectedPosition = abs(selectedPosition % itemCount) - //check if the listener is implemented - //mLastSelectedPosition keeps track of last position which will prevent simple slide and same position + /** + * Check if the listener is implemented + * mLastSelectedPosition keeps track of last position which will prevent simple slide and same position + **/ if (mSelectedListener != null && selectedPosition != mLastSelectedPosition) { mSelectedListener!!.onItemSelected(selectedPosition) } @@ -633,19 +643,19 @@ class CarouselLayoutManager constructor( /** * Calculate the maximum offset */ - private fun maxOffset(): Int{ + private fun maxOffset(): Int { return ((itemCount - 1) * getIntervalDistance()) } /** - * set the selected listener (interface) + * Set the selected listener (interface) */ fun setOnSelectedListener(l: OnSelected) { this.mSelectedListener = l } /** - * set isScrollingEnabled value + * Set isScrollingEnabled value */ fun setIsScrollingEnabled(isScrollingEnabled: Boolean) { this.isScrollingEnabled = isScrollingEnabled @@ -667,7 +677,7 @@ class CarouselLayoutManager constructor( private var isFlat = false private var isAlpha = false - fun setIsInfinite(isInfinite: Boolean) : Builder { + fun setIsInfinite(isInfinite: Boolean): Builder { this.isInfinite = isInfinite return this } @@ -720,7 +730,7 @@ class CarouselLayoutManager constructor( } } - class SaveState constructor(var scrollPosition:Int = 0) : Parcelable { + class SaveState constructor(var scrollPosition: Int = 0) : Parcelable { constructor(parcel: Parcel) : this() { scrollPosition = parcel.readInt() diff --git a/carouselrecyclerview/src/main/java/com/jackandphantom/carouselrecyclerview/CarouselRecyclerview.kt b/carouselrecyclerview/src/main/java/com/jackandphantom/carouselrecyclerview/CarouselRecyclerview.kt index c82408e..9879424 100644 --- a/carouselrecyclerview/src/main/java/com/jackandphantom/carouselrecyclerview/CarouselRecyclerview.kt +++ b/carouselrecyclerview/src/main/java/com/jackandphantom/carouselrecyclerview/CarouselRecyclerview.kt @@ -4,10 +4,10 @@ import android.content.Context import android.os.Bundle import android.os.Parcelable import android.util.AttributeSet -import android.util.Log import androidx.recyclerview.widget.RecyclerView -class CarouselRecyclerview(context: Context, attributeSet: AttributeSet) : RecyclerView(context, attributeSet) { +class CarouselRecyclerview(context: Context, attributeSet: AttributeSet) : + RecyclerView(context, attributeSet) { /** Create layout manager builder so that we can easily add more methods to it */ private var carouselLayoutManagerBuilder: CarouselLayoutManager.Builder = @@ -20,25 +20,23 @@ class CarouselRecyclerview(context: Context, attributeSet: AttributeSet) : Recyc private const val SAVE_LAYOUT_MANAGER = "layout-manager-state" } - /** - * Initialize the layout manager and also enable the childDrawingOrder - */ + /** Initialize the layout manager and also enable the childDrawingOrder */ init { layoutManager = carouselLayoutManagerBuilder.build() isChildrenDrawingOrderEnabled = true } /** - * set the 3d item to the layout manager + * Set the 3d item to the layout manager * @param is3DItem make items in layout manager tilt if true - * */ + */ fun set3DItem(is3DItem: Boolean) { carouselLayoutManagerBuilder.set3DItem(is3DItem) layoutManager = carouselLayoutManagerBuilder.build() } /** - * set the infinite items in the layout manager + * Set the infinite items in the layout manager * @param isInfinite make loop of items * */ fun setInfinite(isInfinite: Boolean) { @@ -77,7 +75,7 @@ class CarouselRecyclerview(context: Context, attributeSet: AttributeSet) : Recyc * Get the layout manager instance * @return CoverLayout */ - fun getCarouselLayoutManager(): CarouselLayoutManager { + fun getCarouselLayoutManager(): CarouselLayoutManager { return layoutManager as CarouselLayoutManager } @@ -91,24 +89,21 @@ class CarouselRecyclerview(context: Context, attributeSet: AttributeSet) : Recyc override fun getChildDrawingOrder(childCount: Int, i: Int): Int { val center: Int = getCarouselLayoutManager().centerPosition() - // Get the actual position of the i-th child view in RecyclerView - - // Get the actual position of the i-th child view in RecyclerView + /** Get the actual position of the i-th child view in RecyclerView */ val actualPos: Int = getCarouselLayoutManager().getChildActualPos(i) - // The number of intervals from the middle item - - // The number of intervals from the middle item + /** The number of intervals from the middle item */ val dist = actualPos - center var order: Int - // [< 0] indicates that the item is located to the left of the middle item and can be drawn in order - // [< 0] indicates that the item is located to the left of the middle item and can be drawn in order + /** [< 0] Indicates that the item is located to the left of the middle item and can be drawn in order */ order = if (dist < 0) { i } else { - //[>= 0] It means that the item is located to the right - // of the middle item, and the order needs to be reversed. + /** + * [>= 0] It means that the item is located to the right + * of the middle item, and the order needs to be reversed. + */ childCount - 1 - dist } @@ -134,7 +129,7 @@ class CarouselRecyclerview(context: Context, attributeSet: AttributeSet) : Recyc layoutManagerState = state.getParcelable(SAVE_LAYOUT_MANAGER) super.onRestoreInstanceState(state.getParcelable(SAVE_SUPER_STATE)) - }else super.onRestoreInstanceState(state) + } else super.onRestoreInstanceState(state) } @@ -145,7 +140,7 @@ class CarouselRecyclerview(context: Context, attributeSet: AttributeSet) : Recyc fun getSelectedPosition() = getCarouselLayoutManager().getSelectedPosition() private fun restorePosition() { - if(layoutManagerState != null) { + if (layoutManagerState != null) { getCarouselLayoutManager().onRestoreInstanceState(layoutManagerState) layoutManagerState = null } diff --git a/carouselrecyclerview/src/main/java/com/jackandphantom/carouselrecyclerview/view/ReflectionImageView.kt b/carouselrecyclerview/src/main/java/com/jackandphantom/carouselrecyclerview/view/ReflectionImageView.kt index 471e03c..6f5b91b 100644 --- a/carouselrecyclerview/src/main/java/com/jackandphantom/carouselrecyclerview/view/ReflectionImageView.kt +++ b/carouselrecyclerview/src/main/java/com/jackandphantom/carouselrecyclerview/view/ReflectionImageView.kt @@ -7,7 +7,8 @@ import android.graphics.drawable.Drawable import android.util.AttributeSet import androidx.appcompat.widget.AppCompatImageView -class ReflectionImageView(context: Context, attrs: AttributeSet): AppCompatImageView(context, attrs) { +class ReflectionImageView(context: Context, attrs: AttributeSet) : + AppCompatImageView(context, attrs) { override fun setImageDrawable(drawable: Drawable?) { if (drawable == null) return @@ -18,10 +19,10 @@ class ReflectionImageView(context: Context, attrs: AttributeSet): AppCompatImage } } - var bitmap:Bitmap? = null - bitmap = if (drawable.intrinsicWidth <= 0|| drawable.intrinsicHeight <= 0) { + var bitmap: Bitmap? = null + bitmap = if (drawable.intrinsicWidth <= 0 || drawable.intrinsicHeight <= 0) { Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888) - }else { + } else { Bitmap.createBitmap( drawable.intrinsicWidth, drawable.intrinsicHeight, diff --git a/carouselrecyclerview/src/main/java/com/jackandphantom/carouselrecyclerview/view/ReflectionViewContainer.kt b/carouselrecyclerview/src/main/java/com/jackandphantom/carouselrecyclerview/view/ReflectionViewContainer.kt index acc3096..5854508 100644 --- a/carouselrecyclerview/src/main/java/com/jackandphantom/carouselrecyclerview/view/ReflectionViewContainer.kt +++ b/carouselrecyclerview/src/main/java/com/jackandphantom/carouselrecyclerview/view/ReflectionViewContainer.kt @@ -42,11 +42,15 @@ import com.jackandphantom.carouselrecyclerview.R class ReflectionViewContainer : LinearLayout { companion object { - // Relative height of the view to generate reflection aka Reflection Depth/Length + /** + * Relative height of the view to generate reflection aka Reflection Depth/Length + **/ private const val DEFAULT_RELATIVE_DEPTH = 0.5f - // Gap b/w the view and the reflection formed - // Same effect can be achieved with padding but the distance will be twice + /** + * Gap b/w the view and the reflection formed + * Same effect can be achieved with padding but the distance will be twice + **/ private const val DEFAULT_GAP = 0.0f } @@ -54,8 +58,14 @@ class ReflectionViewContainer : LinearLayout { private var mRelativeDepth: Float = DEFAULT_RELATIVE_DEPTH private var mReflectionGap: Float = DEFAULT_GAP - // constructor for programmatically adding view - constructor(context: Context, view: View) : super(context, null, R.attr.reflect_reflectionLayoutStyle) { + /** + * constructor for programmatically adding view + **/ + constructor(context: Context, view: View) : super( + context, + null, + R.attr.reflect_reflectionLayoutStyle + ) { addView(view) mReflect = Reflect(this.context).apply { setupView(view, mReflectionGap, mRelativeDepth) @@ -119,15 +129,19 @@ class ReflectionViewContainer : LinearLayout { ) a.recycle() - // Setting the orientation of linear layout as vertical as reflection view should be - // just below the main view + /** + * Setting the orientation of linear layout as vertical as reflection view should be + * just below the main view + **/ orientation = VERTICAL } override fun onFinishInflate() { super.onFinishInflate() - // this guaranties that the reflection is displayed below the main view - // because this method trigger after the layout inflation is done + /** + * This guaranties that the reflection is displayed below the main view + * because this method trigger after the layout inflation is done + */ this.getChildAt(0)?.let { mReflect = Reflect(this.context).apply { setupView(it, mReflectionGap, mRelativeDepth) @@ -204,7 +218,7 @@ class ReflectionViewContainer : LinearLayout { // I didn't find any way around this draw allocation as it required the size of the view mShader = LinearGradient( 0f, - height/2f, 0f, height.toFloat(), 0x7FFFFFFF, 0x00000000, + height / 2f, 0f, height.toFloat(), 0x7FFFFFFF, 0x00000000, Shader.TileMode.CLAMP ) mPaint.shader = mShader @@ -216,8 +230,16 @@ class ReflectionViewContainer : LinearLayout { val p = layoutParams val q = toReflect.layoutParams /** [ MATCHING REFLECTION VIEW DIMENSIONS WITH THE MAIN VIEW ] */ - toReflect.measure(MeasureSpec.makeMeasureSpec(resources.displayMetrics.widthPixels, MeasureSpec.AT_MOST), - MeasureSpec.makeMeasureSpec(resources.displayMetrics.heightPixels, MeasureSpec.AT_MOST)) + toReflect.measure( + MeasureSpec.makeMeasureSpec( + resources.displayMetrics.widthPixels, + MeasureSpec.AT_MOST + ), + MeasureSpec.makeMeasureSpec( + resources.displayMetrics.heightPixels, + MeasureSpec.AT_MOST + ) + ) val msWidth = toReflect.measuredWidth val msHeight = toReflect.measuredHeight @@ -235,11 +257,14 @@ class ReflectionViewContainer : LinearLayout { p.height = (mRelDepth * q.height + mGap + toReflect.paddingBottom).toInt() } else -> { - p.height = (mRelDepth * msHeight).toInt() + p.height = (mRelDepth * msHeight).toInt() } } - this.setMeasuredDimension(toReflect.measuredWidth, (mRelDepth * toReflect.measuredHeight).toInt()) + this.setMeasuredDimension( + toReflect.measuredWidth, + (mRelDepth * toReflect.measuredHeight).toInt() + ) layoutParams = p /** END */ @@ -252,18 +277,18 @@ class ReflectionViewContainer : LinearLayout { canvas.save() val cx = width / 2f val cy = height / 2f - // rotating, flipping and translating the canvas to create the required mirror image. + /** Rotating, flipping and translating the canvas to create the required mirror image.*/ canvas.rotate(-180f, cx, cy) canvas.scale(-1f, 1f, cx, cy) - val gap = height - mRelDepth * toReflect.height + val gap = height - mRelDepth * toReflect.height val mTranslateY = toReflect.height - height + gap canvas.translate(0f, -mTranslateY) canvas.clipRect(left, top, width, height) toReflect.draw(canvas) canvas.restore() - canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), mPaint) + canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), mPaint) } } }