| @ -0,0 +1,33 @@ | |||
| package com.nivesh.production.niveshfd.fd.util.attacher | |||
| import com.nivesh.production.niveshfd.fd.util.dotIndicator.BaseDotsIndicator | |||
| internal abstract class DotsIndicatorAttacher<Attachable, Adapter> { | |||
| fun setup(baseDotsIndicator: BaseDotsIndicator, attachable: Attachable) { | |||
| val adapter = getAdapterFromAttachable(attachable) | |||
| ?: throw IllegalStateException( | |||
| "Please set an adapter to the view pager (1 or 2) or the recycler before initializing the dots indicator" | |||
| ) | |||
| registerAdapterDataChangedObserver(attachable, adapter) { | |||
| baseDotsIndicator.post { baseDotsIndicator.refreshDots() } | |||
| } | |||
| baseDotsIndicator.pager = buildPager(attachable, adapter) | |||
| baseDotsIndicator.refreshDots() | |||
| } | |||
| abstract fun getAdapterFromAttachable(attachable: Attachable): Adapter? | |||
| abstract fun registerAdapterDataChangedObserver( | |||
| attachable: Attachable, | |||
| adapter: Adapter, | |||
| onChanged: () -> Unit | |||
| ) | |||
| abstract fun buildPager( | |||
| attachable: Attachable, | |||
| adapter: Adapter, | |||
| ): BaseDotsIndicator.Pager | |||
| } | |||
| @ -0,0 +1,66 @@ | |||
| package com.nivesh.production.niveshfd.fd.util.attacher | |||
| import android.database.DataSetObserver | |||
| import androidx.viewpager.widget.PagerAdapter | |||
| import androidx.viewpager.widget.ViewPager | |||
| import com.nivesh.production.niveshfd.fd.util.dotIndicator.BaseDotsIndicator | |||
| import com.nivesh.production.niveshfd.fd.util.dotIndicator.OnPageChangeListenerHelper | |||
| import com.nivesh.production.niveshfd.fd.util.dotIndicator.isEmpty | |||
| internal class ViewPagerAttacher : | |||
| DotsIndicatorAttacher<ViewPager, PagerAdapter>() { | |||
| override fun getAdapterFromAttachable(attachable: ViewPager): PagerAdapter? = attachable.adapter | |||
| override fun registerAdapterDataChangedObserver( | |||
| attachable: ViewPager, | |||
| adapter: PagerAdapter, | |||
| onChanged: () -> Unit | |||
| ) { | |||
| adapter.registerDataSetObserver(object : DataSetObserver() { | |||
| override fun onChanged() { | |||
| super.onChanged() | |||
| onChanged() | |||
| } | |||
| }) | |||
| } | |||
| override fun buildPager(attachable: ViewPager, adapter: PagerAdapter): BaseDotsIndicator.Pager { | |||
| return object : BaseDotsIndicator.Pager { | |||
| var onPageChangeListener: ViewPager.OnPageChangeListener? = null | |||
| override val isNotEmpty: Boolean get() = attachable.isEmpty | |||
| override val currentItem: Int get() = attachable.currentItem | |||
| override val isEmpty: Boolean get() = attachable.isEmpty | |||
| override val count: Int get() = attachable.adapter?.count ?: 0 | |||
| override fun setCurrentItem(item: Int, smoothScroll: Boolean) { | |||
| attachable.setCurrentItem(item, smoothScroll) | |||
| } | |||
| override fun removeOnPageChangeListener() { | |||
| onPageChangeListener?.let { attachable.removeOnPageChangeListener(it) } | |||
| } | |||
| override fun addOnPageChangeListener( | |||
| onPageChangeListenerHelper: | |||
| OnPageChangeListenerHelper | |||
| ) { | |||
| onPageChangeListener = object : ViewPager.OnPageChangeListener { | |||
| override fun onPageScrolled( | |||
| position: Int, positionOffset: Float, | |||
| positionOffsetPixels: Int | |||
| ) { | |||
| onPageChangeListenerHelper.onPageScrolled(position, positionOffset) | |||
| } | |||
| override fun onPageScrollStateChanged(state: Int) { | |||
| } | |||
| override fun onPageSelected(position: Int) { | |||
| } | |||
| } | |||
| attachable.addOnPageChangeListener(onPageChangeListener!!) | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,227 @@ | |||
| package com.nivesh.production.niveshfd.fd.util.dotIndicator | |||
| import android.content.Context | |||
| import android.graphics.Color | |||
| import android.os.Build | |||
| import android.os.Parcelable | |||
| import android.util.AttributeSet | |||
| import android.view.View | |||
| import android.widget.FrameLayout | |||
| import android.widget.ImageView | |||
| import androidx.annotation.StyleableRes | |||
| import androidx.viewpager.widget.ViewPager | |||
| import androidx.viewpager2.widget.ViewPager2 | |||
| import com.nivesh.production.niveshfd.R | |||
| import com.nivesh.production.niveshfd.fd.util.attacher.ViewPagerAttacher | |||
| abstract class BaseDotsIndicator @JvmOverloads constructor( | |||
| context: Context, | |||
| attrs: AttributeSet? = null, | |||
| defStyleAttr: Int = 0 | |||
| ) : FrameLayout(context, attrs, defStyleAttr) { | |||
| companion object { | |||
| const val DEFAULT_POINT_COLOR = Color.CYAN | |||
| } | |||
| enum class Type( | |||
| val defaultSize: Float, | |||
| val defaultSpacing: Float, | |||
| @StyleableRes val styleableId: IntArray, | |||
| @StyleableRes val dotsColorId: Int, | |||
| @StyleableRes val dotsSizeId: Int, | |||
| @StyleableRes val dotsSpacingId: Int, | |||
| @StyleableRes val dotsCornerRadiusId: Int, | |||
| @StyleableRes val dotsClickableId: Int | |||
| ) { | |||
| DEFAULT( | |||
| 16f, | |||
| 8f, | |||
| R.styleable.SpringDotsIndicator, | |||
| R.styleable.SpringDotsIndicator_dotsColor, | |||
| R.styleable.SpringDotsIndicator_dotsSize, | |||
| R.styleable.SpringDotsIndicator_dotsSpacing, | |||
| R.styleable.SpringDotsIndicator_dotsCornerRadius, | |||
| R.styleable.SpringDotsIndicator_dotsClickable | |||
| ), | |||
| SPRING( | |||
| 16f, | |||
| 4f, | |||
| R.styleable.DotsIndicator, | |||
| R.styleable.DotsIndicator_dotsColor, | |||
| R.styleable.DotsIndicator_dotsSize, | |||
| R.styleable.DotsIndicator_dotsSpacing, | |||
| R.styleable.DotsIndicator_dotsCornerRadius, | |||
| R.styleable.SpringDotsIndicator_dotsClickable | |||
| ), | |||
| WORM( | |||
| 16f, | |||
| 4f, | |||
| R.styleable.WormDotsIndicator, | |||
| R.styleable.WormDotsIndicator_dotsColor, | |||
| R.styleable.WormDotsIndicator_dotsSize, | |||
| R.styleable.WormDotsIndicator_dotsSpacing, | |||
| R.styleable.WormDotsIndicator_dotsCornerRadius, | |||
| R.styleable.SpringDotsIndicator_dotsClickable | |||
| ) | |||
| } | |||
| @JvmField | |||
| protected val dots = ArrayList<ImageView>() | |||
| var dotsClickable: Boolean = true | |||
| var dotsColor: Int = DEFAULT_POINT_COLOR | |||
| set(value) { | |||
| field = value | |||
| refreshDotsColors() | |||
| } | |||
| protected var dotsSize = dpToPxF(type.defaultSize) | |||
| protected var dotsCornerRadius = dotsSize / 2f | |||
| protected var dotsSpacing = dpToPxF(type.defaultSpacing) | |||
| init { | |||
| if (attrs != null) { | |||
| val a = context.obtainStyledAttributes(attrs, type.styleableId) | |||
| dotsColor = a.getColor(type.dotsColorId, DEFAULT_POINT_COLOR) | |||
| dotsSize = a.getDimension(type.dotsSizeId, dotsSize) | |||
| dotsCornerRadius = a.getDimension(type.dotsCornerRadiusId, dotsCornerRadius) | |||
| dotsSpacing = a.getDimension(type.dotsSpacingId, dotsSpacing) | |||
| dotsClickable = a.getBoolean(type.dotsClickableId, true) | |||
| a.recycle() | |||
| } | |||
| } | |||
| var pager: Pager? = null | |||
| interface Pager { | |||
| val isNotEmpty: Boolean | |||
| val currentItem: Int | |||
| val isEmpty: Boolean | |||
| val count: Int | |||
| fun setCurrentItem(item: Int, smoothScroll: Boolean) | |||
| fun removeOnPageChangeListener() | |||
| fun addOnPageChangeListener(onPageChangeListenerHelper: OnPageChangeListenerHelper) | |||
| } | |||
| override fun onAttachedToWindow() { | |||
| super.onAttachedToWindow() | |||
| post { refreshDots() } | |||
| } | |||
| private fun refreshDotsCount() { | |||
| if (dots.size < pager!!.count) { | |||
| addDots(pager!!.count - dots.size) | |||
| } else if (dots.size > pager!!.count) { | |||
| removeDots(dots.size - pager!!.count) | |||
| } | |||
| } | |||
| protected fun refreshDotsColors() { | |||
| for (i in dots.indices) { | |||
| refreshDotColor(i) | |||
| } | |||
| } | |||
| protected fun dpToPx(dp: Int): Int { | |||
| return (context.resources.displayMetrics.density * dp).toInt() | |||
| } | |||
| protected fun dpToPxF(dp: Float): Float { | |||
| return context.resources.displayMetrics.density * dp | |||
| } | |||
| protected fun addDots(count: Int) { | |||
| for (i in 0 until count) { | |||
| addDot(i) | |||
| } | |||
| } | |||
| private fun removeDots(count: Int) { | |||
| for (i in 0 until count) { | |||
| removeDot() | |||
| } | |||
| } | |||
| fun refreshDots() { | |||
| if (pager == null) { | |||
| return | |||
| } | |||
| post { | |||
| // Check if we need to refresh the dots count | |||
| refreshDotsCount() | |||
| refreshDotsColors() | |||
| refreshDotsSize() | |||
| refreshOnPageChangedListener() | |||
| } | |||
| } | |||
| private fun refreshOnPageChangedListener() { | |||
| if (pager!!.isNotEmpty) { | |||
| pager!!.removeOnPageChangeListener() | |||
| val onPageChangeListenerHelper = buildOnPageChangedListener() | |||
| pager!!.addOnPageChangeListener(onPageChangeListenerHelper) | |||
| onPageChangeListenerHelper.onPageScrolled(pager!!.currentItem, 0f) | |||
| } | |||
| } | |||
| private fun refreshDotsSize() { | |||
| dots.forEach { it.setWidth(dotsSize.toInt()) } | |||
| } | |||
| // ABSTRACT METHODS AND FIELDS | |||
| abstract fun refreshDotColor(index: Int) | |||
| abstract fun addDot(index: Int) | |||
| abstract fun removeDot() | |||
| abstract fun buildOnPageChangedListener(): OnPageChangeListenerHelper | |||
| abstract val type: Type | |||
| // PUBLIC METHODS | |||
| @Deprecated( | |||
| "Use setDotsColors(color) instead", ReplaceWith("setDotsColors(color)") | |||
| ) | |||
| fun setPointsColor(color: Int) { | |||
| dotsColor = color | |||
| refreshDotsColors() | |||
| } | |||
| @Deprecated( | |||
| "Use attachTo(viewPager) instead", ReplaceWith("attachTo(viewPager)") | |||
| ) | |||
| fun setViewPager(viewPager: ViewPager) { | |||
| ViewPagerAttacher().setup(this, viewPager) | |||
| } | |||
| @Deprecated( | |||
| "Use attachTo(viewPager) instead", ReplaceWith("attachTo(viewPager)") | |||
| ) | |||
| // fun setViewPager2(viewPager2: ViewPager2) { | |||
| // ViewPager2Attacher().setup(this, viewPager2) | |||
| // } | |||
| fun attachTo(viewPager: ViewPager) { | |||
| ViewPagerAttacher().setup(this, viewPager) | |||
| } | |||
| // fun attachTo(viewPager2: ViewPager2) { | |||
| // ViewPager2Attacher().setup(this, viewPager2) | |||
| // } | |||
| override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { | |||
| super.onLayout(changed, left, top, right, bottom) | |||
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && layoutDirection == View.LAYOUT_DIRECTION_RTL) { | |||
| layoutDirection = View.LAYOUT_DIRECTION_LTR | |||
| rotation = 180f | |||
| requestLayout() | |||
| } | |||
| } | |||
| override fun onRestoreInstanceState(state: Parcelable?) { | |||
| super.onRestoreInstanceState(state) | |||
| post { refreshDots() } | |||
| } | |||
| } | |||
| @ -0,0 +1,13 @@ | |||
| package com.nivesh.production.niveshfd.fd.util.dotIndicator | |||
| import android.graphics.drawable.GradientDrawable | |||
| class DotsGradientDrawable : GradientDrawable() { | |||
| var currentColor: Int = 0 | |||
| private set | |||
| override fun setColor(argb: Int) { | |||
| super.setColor(argb) | |||
| currentColor = argb | |||
| } | |||
| } | |||
| @ -0,0 +1,205 @@ | |||
| package com.nivesh.production.niveshfd.fd.util.dotIndicator | |||
| import android.animation.ArgbEvaluator | |||
| import android.content.Context | |||
| import android.os.Build | |||
| import android.util.AttributeSet | |||
| import android.util.Log | |||
| import android.view.LayoutInflater | |||
| import android.view.View | |||
| import android.view.ViewGroup | |||
| import android.widget.ImageView | |||
| import android.widget.LinearLayout | |||
| import com.nivesh.production.niveshfd.R | |||
| class DotsIndicator @JvmOverloads constructor( | |||
| context: Context, attrs: AttributeSet? = null, | |||
| defStyleAttr: Int = 0 | |||
| ) : BaseDotsIndicator(context, attrs, defStyleAttr) { | |||
| companion object { | |||
| const val DEFAULT_WIDTH_FACTOR = 2.5f | |||
| } | |||
| private lateinit var linearLayout: LinearLayout | |||
| private var dotsWidthFactor: Float = 0f | |||
| private var progressMode: Boolean = false | |||
| private var dotsElevation: Float = 0f | |||
| var selectedDotColor: Int = 0 | |||
| set(value) { | |||
| field = value | |||
| refreshDotsColors() | |||
| } | |||
| private val argbEvaluator = ArgbEvaluator() | |||
| init { | |||
| init(attrs) | |||
| } | |||
| private fun init(attrs: AttributeSet?) { | |||
| linearLayout = LinearLayout(context) | |||
| linearLayout.orientation = LinearLayout.HORIZONTAL | |||
| addView(linearLayout, | |||
| ViewGroup.LayoutParams.WRAP_CONTENT, | |||
| ViewGroup.LayoutParams.WRAP_CONTENT | |||
| ) | |||
| dotsWidthFactor = DEFAULT_WIDTH_FACTOR | |||
| if (attrs != null) { | |||
| val a = context.obtainStyledAttributes(attrs, R.styleable.DotsIndicator) | |||
| selectedDotColor = | |||
| a.getColor(R.styleable.DotsIndicator_selectedDotColor, DEFAULT_POINT_COLOR) | |||
| dotsWidthFactor = a.getFloat(R.styleable.DotsIndicator_dotsWidthFactor, 2.5f) | |||
| if (dotsWidthFactor < 1) { | |||
| Log.w( | |||
| "DotsIndicator", | |||
| "The dotsWidthFactor can't be set under 1.0f, please set an higher value" | |||
| ) | |||
| dotsWidthFactor = 1f | |||
| } | |||
| progressMode = a.getBoolean(R.styleable.DotsIndicator_progressMode, false) | |||
| dotsElevation = a.getDimension(R.styleable.DotsIndicator_dotsElevation, 0f) | |||
| a.recycle() | |||
| } | |||
| if (isInEditMode) { | |||
| addDots(5) | |||
| refreshDots() | |||
| } | |||
| } | |||
| override fun addDot(index: Int) { | |||
| val dot = LayoutInflater.from(context).inflate(R.layout.dot_layout, this, false) | |||
| val imageView = dot.findViewById<ImageView>(R.id.dot) | |||
| val params = imageView.layoutParams as LayoutParams | |||
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { | |||
| dot.layoutDirection = View.LAYOUT_DIRECTION_LTR | |||
| } | |||
| params.height = dotsSize.toInt() | |||
| params.width = params.height | |||
| params.setMargins(dotsSpacing.toInt(), 0, dotsSpacing.toInt(), 0) | |||
| val background = DotsGradientDrawable() | |||
| background.cornerRadius = dotsCornerRadius | |||
| if (isInEditMode) { | |||
| background.setColor(if (0 == index) selectedDotColor else dotsColor) | |||
| } else { | |||
| background.setColor(if (pager!!.currentItem == index) selectedDotColor else dotsColor) | |||
| } | |||
| imageView.setBackgroundCompat(background) | |||
| dot.setOnClickListener { | |||
| if (dotsClickable && index < pager?.count ?: 0) { | |||
| pager!!.setCurrentItem(index, true) | |||
| } | |||
| } | |||
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | |||
| dot.setPaddingHorizontal((dotsElevation * 0.8f).toInt()) | |||
| dot.setPaddingVertical((dotsElevation * 2).toInt()) | |||
| imageView.elevation = dotsElevation | |||
| } | |||
| dots.add(imageView) | |||
| linearLayout.addView(dot) | |||
| } | |||
| override fun removeDot() { | |||
| linearLayout.removeViewAt(linearLayout.childCount - 1) | |||
| dots.removeAt(dots.size - 1) | |||
| } | |||
| override fun buildOnPageChangedListener(): OnPageChangeListenerHelper { | |||
| return object : OnPageChangeListenerHelper() { | |||
| override fun onPageScrolled( | |||
| selectedPosition: Int, | |||
| nextPosition: Int, | |||
| positionOffset: Float | |||
| ) { | |||
| val selectedDot = dots[selectedPosition] | |||
| // Selected dot | |||
| val selectedDotWidth = | |||
| (dotsSize + dotsSize * (dotsWidthFactor - 1) * (1 - positionOffset)).toInt() | |||
| selectedDot.setWidth(selectedDotWidth) | |||
| if (dots.isInBounds(nextPosition)) { | |||
| val nextDot = dots[nextPosition] | |||
| val nextDotWidth = | |||
| (dotsSize + dotsSize * (dotsWidthFactor - 1) * positionOffset).toInt() | |||
| nextDot.setWidth(nextDotWidth) | |||
| val selectedDotBackground = selectedDot.background as DotsGradientDrawable | |||
| val nextDotBackground = nextDot.background as DotsGradientDrawable | |||
| if (selectedDotColor != dotsColor) { | |||
| val selectedColor = argbEvaluator.evaluate( | |||
| positionOffset, selectedDotColor, | |||
| dotsColor | |||
| ) as Int | |||
| val nextColor = argbEvaluator.evaluate( | |||
| positionOffset, dotsColor, | |||
| selectedDotColor | |||
| ) as Int | |||
| nextDotBackground.setColor(nextColor) | |||
| if (progressMode && selectedPosition <= pager!!.currentItem) { | |||
| selectedDotBackground.setColor(selectedDotColor) | |||
| } else { | |||
| selectedDotBackground.setColor(selectedColor) | |||
| } | |||
| } | |||
| } | |||
| invalidate() | |||
| } | |||
| override fun resetPosition(position: Int) { | |||
| dots[position].setWidth(dotsSize.toInt()) | |||
| refreshDotColor(position) | |||
| } | |||
| override val pageCount: Int | |||
| get() = dots.size | |||
| } | |||
| } | |||
| override fun refreshDotColor(index: Int) { | |||
| val elevationItem = dots[index] | |||
| val background = elevationItem.background as? DotsGradientDrawable? | |||
| background?.let { | |||
| if (index == pager!!.currentItem || progressMode && index < pager!!.currentItem) { | |||
| background.setColor(selectedDotColor) | |||
| } else { | |||
| background.setColor(dotsColor) | |||
| } | |||
| } | |||
| elevationItem.setBackgroundCompat(background) | |||
| elevationItem.invalidate() | |||
| } | |||
| override val type get() = Type.DEFAULT | |||
| //********************************************************* | |||
| // Users Methods | |||
| //********************************************************* | |||
| @Deprecated("Use setSelectedDotColor() instead", ReplaceWith("setSelectedDotColor()")) | |||
| fun setSelectedPointColor(color: Int) { | |||
| selectedDotColor = color | |||
| } | |||
| } | |||
| @ -0,0 +1,46 @@ | |||
| package com.nivesh.production.niveshfd.fd.util.dotIndicator | |||
| import android.content.Context | |||
| import android.graphics.drawable.Drawable | |||
| import android.os.Build | |||
| import android.util.TypedValue | |||
| import android.view.View | |||
| import androidx.viewpager.widget.ViewPager | |||
| import androidx.viewpager2.widget.ViewPager2 | |||
| import com.nivesh.production.niveshfd.R | |||
| internal fun View.setPaddingHorizontal(padding: Int) { | |||
| setPadding(padding, paddingTop, padding, paddingBottom) | |||
| } | |||
| internal fun View.setPaddingVertical(padding: Int) { | |||
| setPadding(paddingLeft, padding, paddingRight, padding) | |||
| } | |||
| internal fun View.setWidth(width: Int) { | |||
| layoutParams.apply { | |||
| this.width = width | |||
| requestLayout() | |||
| } | |||
| } | |||
| internal fun <T> ArrayList<T>.isInBounds(index: Int) = index in 0 until size | |||
| internal fun Context.getThemePrimaryColor(): Int { | |||
| val value = TypedValue() | |||
| this.theme.resolveAttribute(androidx.transition.R.attr.colorPrimary, value, true) | |||
| return value.data | |||
| } | |||
| internal val ViewPager.isNotEmpty: Boolean get() = (adapter?.count ?: 0) > 0 | |||
| internal val ViewPager2.isNotEmpty: Boolean get() = (adapter?.itemCount ?: 0) > 0 | |||
| internal val ViewPager?.isEmpty: Boolean get() = this?.adapter?.count == 0 | |||
| internal val ViewPager2?.isEmpty: Boolean get() = this?.adapter?.itemCount == 0 | |||
| fun View.setBackgroundCompat(background: Drawable?) { | |||
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { | |||
| this.background = background | |||
| } else { | |||
| setBackgroundDrawable(background) | |||
| } | |||
| } | |||
| @ -0,0 +1,49 @@ | |||
| package com.nivesh.production.niveshfd.fd.util.dotIndicator | |||
| abstract class OnPageChangeListenerHelper { | |||
| private var lastLeftPosition: Int = -1 | |||
| private var lastRightPosition: Int = -1 | |||
| internal abstract val pageCount: Int | |||
| fun onPageScrolled(position: Int, positionOffset: Float) { | |||
| var offset = (position + positionOffset) | |||
| val lastPageIndex = (pageCount - 1).toFloat() | |||
| if (offset == lastPageIndex) { | |||
| offset = lastPageIndex - .0001f | |||
| } | |||
| val leftPosition = offset.toInt() | |||
| val rightPosition = leftPosition + 1 | |||
| if (rightPosition > lastPageIndex || leftPosition < 0) { | |||
| return | |||
| } | |||
| onPageScrolled(leftPosition, rightPosition, offset % 1) | |||
| if (lastLeftPosition != -1) { | |||
| if (leftPosition > lastLeftPosition) { | |||
| (lastLeftPosition until leftPosition).forEach { | |||
| resetPosition(it) | |||
| } | |||
| } | |||
| if (rightPosition < lastRightPosition) { | |||
| resetPosition(lastRightPosition) | |||
| ((rightPosition + 1)..lastRightPosition).forEach { | |||
| resetPosition(it) | |||
| } | |||
| } | |||
| } | |||
| lastLeftPosition = leftPosition | |||
| lastRightPosition = rightPosition | |||
| } | |||
| internal abstract fun onPageScrolled( | |||
| selectedPosition: Int, nextPosition: Int, | |||
| positionOffset: Float | |||
| ) | |||
| internal abstract fun resetPosition(position: Int) | |||
| } | |||
| @ -0,0 +1,7 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <set xmlns:android="http://schemas.android.com/apk/res/android" > | |||
| <translate | |||
| android:duration="1000" | |||
| android:fromYDelta="0" | |||
| android:toYDelta="100%" /> | |||
| </set> | |||
| @ -0,0 +1,4 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <translate xmlns:android="http://schemas.android.com/apk/res/android" | |||
| android:fromYDelta="50%p" android:toYDelta="0%p" | |||
| android:duration="@android:integer/config_longAnimTime"/> | |||
| @ -0,0 +1,6 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" | |||
| android:shape="rectangle"> | |||
| <solid android:color="@android:color/white" /> | |||
| <corners android:radius="0dp" /> | |||
| </shape> | |||
| @ -0,0 +1,9 @@ | |||
| <shape xmlns:android="http://schemas.android.com/apk/res/android"> | |||
| <solid android:color="@color/white" /> | |||
| <stroke android:width="1dp" android:color="@color/greyColor1" /> | |||
| <padding android:left="15dp" android:top="15dp" android:right="15dp" android:bottom="10dp" /> | |||
| <corners android:topLeftRadius="36dp" | |||
| android:topRightRadius="36dp" | |||
| android:bottomLeftRadius="1dp" | |||
| android:bottomRightRadius="1dp"/> | |||
| </shape> | |||
| @ -1,5 +1,20 @@ | |||
| <vector android:height="24dp" android:tint="#000000" | |||
| android:viewportHeight="24" android:viewportWidth="24" | |||
| android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> | |||
| <path android:fillColor="@android:color/white" android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/> | |||
| </vector> | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | |||
| android:width="50dp" | |||
| android:height="50dp" | |||
| android:viewportWidth="50" | |||
| android:viewportHeight="50"> | |||
| <path | |||
| android:strokeColor="#ffffff" | |||
| android:strokeWidth="2" | |||
| android:pathData="M 25 1 C 38.2548339959 1 49 11.7451660041 49 25 C 49 38.2548339959 38.2548339959 49 25 49 C 11.7451660041 49 1 38.2548339959 1 25 C 1 11.7451660041 11.7451660041 1 25 1 Z" /> | |||
| <path | |||
| android:strokeColor="#ffffff" | |||
| android:strokeWidth="2" | |||
| android:pathData="M 15.7071 14.2929 L 35.5061 34.0919" /> | |||
| <path | |||
| android:strokeColor="#ffffff" | |||
| android:strokeWidth="2" | |||
| android:pathData="M 14.2929 34.2929 L 34.0919 14.4939" /> | |||
| </vector> | |||
| @ -0,0 +1,20 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | |||
| android:width="50dp" | |||
| android:height="50dp" | |||
| android:viewportWidth="50" | |||
| android:viewportHeight="50"> | |||
| <path | |||
| android:strokeColor="#ffffff" | |||
| android:strokeWidth="2" | |||
| android:pathData="M 25 1 C 38.2548339959 1 49 11.7451660041 49 25 C 49 38.2548339959 38.2548339959 49 25 49 C 11.7451660041 49 1 38.2548339959 1 25 C 1 11.7451660041 11.7451660041 1 25 1 Z" /> | |||
| <path | |||
| android:strokeColor="#ffffff" | |||
| android:strokeWidth="2" | |||
| android:pathData="M 15.7071 14.2929 L 35.5061 34.0919" /> | |||
| <path | |||
| android:strokeColor="#ffffff" | |||
| android:strokeWidth="2" | |||
| android:pathData="M 14.2929 34.2929 L 34.0919 14.4939" /> | |||
| </vector> | |||
| @ -0,0 +1,15 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:layout_gravity="center_vertical" | |||
| android:clipToPadding="false"> | |||
| <ImageView | |||
| android:id="@+id/dot" | |||
| android:layout_width="8dp" | |||
| android:layout_height="8dp" | |||
| android:layout_gravity="center" | |||
| android:background="@drawable/dot_background" /> | |||
| </FrameLayout> | |||
| @ -0,0 +1,28 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
| android:layout_width="match_parent" | |||
| android:layout_height="match_parent"> | |||
| <ImageView | |||
| android:id="@+id/imageCross" | |||
| android:layout_width="wrap_content" | |||
| android:layout_height="wrap_content" | |||
| android:contentDescription="@string/cancel" | |||
| android:layout_centerHorizontal="true" | |||
| android:src="@drawable/svg_close" /> | |||
| <LinearLayout | |||
| android:layout_width="match_parent" | |||
| android:layout_height="match_parent" | |||
| android:orientation="vertical" | |||
| android:background="@drawable/round_corner_top" | |||
| android:layout_marginTop="@dimen/margin_60"> | |||
| <WebView | |||
| android:id="@+id/webView" | |||
| android:layout_width="match_parent" | |||
| android:layout_height="match_parent" /> | |||
| </LinearLayout> | |||
| </RelativeLayout> | |||
Powered by TurnKey Linux.