From b490951a742429fbc95329ac45ee339f715f8602 Mon Sep 17 00:00:00 2001 From: Parminder Singh Date: Sun, 12 Aug 2018 00:50:17 +0530 Subject: [PATCH 01/11] Initial commit --- LICENSE | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From e6ad5a0768b8f047ba5fe1144492f5ab5b4d3d03 Mon Sep 17 00:00:00 2001 From: Parm Singh Date: Tue, 14 Aug 2018 14:26:40 +0530 Subject: [PATCH 02/11] master: formatting & child view made accessible --- .idea/caches/build_file_checksums.ser | Bin 535 -> 535 bytes .../java/params/com/statusView/StatusView.kt | 294 +++++++++--------- 2 files changed, 145 insertions(+), 149 deletions(-) diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 7a1d625052a20e45c17a649e1d059bb3e203be4c..a016d0c7198ea2a0344e05149d54eba5b6c7d4d7 100644 GIT binary patch delta 36 ucmV+<0NekU1eXMmm;^OhpnkEO4*?LlC}HwS8lv?*=a%$jq - if(ViewCompat.isLaidOut(this)){ + if (ViewCompat.isLaidOut(this)) { initCirclePaints() val oldHadStrokeFlagSet = containsFlag(old, CIRCLE_COLOR_TYPE_STROKE) val newHasStrokeFlagSet = containsFlag(new, CIRCLE_COLOR_TYPE_STROKE) - if((oldHadStrokeFlagSet && !newHasStrokeFlagSet) || (!oldHadStrokeFlagSet && newHasStrokeFlagSet)) - { + if ((oldHadStrokeFlagSet && !newHasStrokeFlagSet) || (!oldHadStrokeFlagSet && newHasStrokeFlagSet)) { requestLayout() - }else{ + } else { setDrawingDimensions() invalidate() } @@ -357,12 +357,12 @@ class StatusView @JvmOverloads constructor( * To the caller. It is a list of string and custom getter setters have been made accordingly * */ - private var statusData:MutableList by OnLayoutProp(mutableListOf()) + private var statusData: MutableList by OnLayoutProp(mutableListOf()) /** * Extracts List from List and returns back to the caller */ - fun getStatusList():List = statusData.map { it.text } + fun getStatusList(): List = statusData.map { it.text } /** * Creates List from List by passing default values. @@ -370,9 +370,9 @@ class StatusView @JvmOverloads constructor( */ fun setStatusList(list: List) { //to make sure original list is not modified convert to mutableList - val input = list.toMutableList().dropLast(stepCount) + val input = list.toMutableList().dropLast(stepCount) - statusData = (input.map{StatusInfo(it)}).toMutableList() + statusData = (input.map { StatusInfo(it) }).toMutableList() } @@ -382,14 +382,12 @@ class StatusView @JvmOverloads constructor( * Stores all the drawing data that is used while drawing on canvas */ private var drawingData = mutableListOf() - private var currentStatusRadius:Float by OnLayoutProp(circleRadius) + private var currentStatusRadius: Float by OnLayoutProp(circleRadius) private var lineLengthComputed = 0.0f //actual linelength that is calculated and set - - //To store the data of each circle - private class Item(val textData: LabelItemText?, val circleItem: CircleItem, val lineItem: LineItem?, val labelData: StatusItemText?=null) + private class Item(val textData: LabelItemText?, val circleItem: CircleItem, val lineItem: LineItem?, val labelData: StatusItemText? = null) //Stores drawing data about labels to be drawn inside circles i.e the count of step private class LabelItemText(val text: String? = null, val paint: Paint? = null, val x: Float = 0.0f, val y: Float = 0.0f, val drawableItem: DrawableItem? = null) @@ -407,13 +405,12 @@ class StatusView @JvmOverloads constructor( private class DrawableItem(val rect: Rect, val drawable: Drawable) //Stores information about every status text and its dimension properties - private class StatusInfo(val text:String, var width:Float=0.0f, var height:Float=0.0f, var staticLayout: StaticLayout? = null) - + private class StatusInfo(val text: String, var width: Float = 0.0f, var height: Float = 0.0f, var staticLayout: StaticLayout? = null) init { - id = ViewCompat.generateViewId()//as the same attrs are being passed this view would have the same id as scroller. + id = ViewCompat.generateViewId()//as the same attrs are being passed this view would have the same id as scroller. val a = context.theme.obtainStyledAttributes(attrs, R.styleable.StatusViewScroller, 0, 0) @@ -444,7 +441,7 @@ class StatusView @JvmOverloads constructor( textColorLabelsIncomplete = a.getColor(R.styleable.StatusViewScroller_textColorLabelsIncomplete, textColorLabels) textColorLabelCurrent = a.getColor(R.styleable.StatusViewScroller_textColorLabelsCurrent, textColorLabelsIncomplete) lineColorIncomplete = a.getColor(R.styleable.StatusViewScroller_lineColorIncomplete, lineColor) - lineColorCurrent= a.getColor(R.styleable.StatusViewScroller_lineColorCurrent, lineColorIncomplete) + lineColorCurrent = a.getColor(R.styleable.StatusViewScroller_lineColorCurrent, lineColorIncomplete) circleFillColorIncomplete = a.getColor(R.styleable.StatusViewScroller_circleColorIncomplete, circleFillColor) circleStrokeColorIncomplete = a.getColor(R.styleable.StatusViewScroller_circleStrokeColorIncomplete, circleStrokeColor) circleStrokeColorCurrent = a.getColor(R.styleable.StatusViewScroller_circleStrokeColorCurrent, circleStrokeColorIncomplete) @@ -454,7 +451,7 @@ class StatusView @JvmOverloads constructor( val entries = a.getTextArray(R.styleable.StatusViewScroller_android_entries) if (entries != null) { - for(entry in entries){ + for (entry in entries) { statusData.add(StatusInfo(entry.toString())) } } @@ -529,7 +526,6 @@ class StatusView @JvmOverloads constructor( } - } private fun initCirclePaints() { @@ -549,7 +545,7 @@ class StatusView @JvmOverloads constructor( } } - if(isShowingCurrentStatus()){ + if (isShowingCurrentStatus()) { if (mCircleStrokePaintCurrent == null) { mCircleStrokePaintCurrent = Paint(mCircleStrokePaint) mCircleStrokePaintCurrent?.color = circleStrokeColorCurrent @@ -576,7 +572,7 @@ class StatusView @JvmOverloads constructor( } } - if(isShowingCurrentStatus()){ + if (isShowingCurrentStatus()) { if (mCircleFillPaintCurrent == null) { mCircleFillPaintCurrent = Paint(mCircleFillPaint) mCircleFillPaintCurrent?.color = circleFillColorCurrent @@ -584,8 +580,8 @@ class StatusView @JvmOverloads constructor( } } else { mCircleFillPaint = null - mCircleFillPaintIncomplete =null - mCircleFillPaintCurrent=null + mCircleFillPaintIncomplete = null + mCircleFillPaintCurrent = null } } @@ -593,7 +589,7 @@ class StatusView @JvmOverloads constructor( private fun isShowingIncompleteStatus() = currentCount > INVALID_STATUS_COUNT && currentCount < stepCount - private fun isShowingCurrentStatus()= + private fun isShowingCurrentStatus() = currentCount in 1..stepCount @@ -601,40 +597,38 @@ class StatusView @JvmOverloads constructor( lineLengthComputed = lineLength - var extraWidth = if(strictObeyLineLength){// extra width required by status at extreme positions + var extraWidth = if (strictObeyLineLength) {// extra width required by status at extreme positions setWidthDataForObeyingLineLength() - }else{ + } else { setWidthDataForObeyingStatusText() } - if(isShowingCurrentStatus()){ - extraWidth += (currentStatusRadius-circleRadius)*2 + if (isShowingCurrentStatus()) { + extraWidth += (currentStatusRadius - circleRadius) * 2 } - if(stepCount==1) { + if (stepCount == 1) { extraWidth *= 2 } - return ((stepCount * (2 * (circleRadius + (circleStrokeWidth/2)))) + - ((stepCount - 1) * ( lineLengthComputed + (lineGap * 2))) + extraWidth).toInt() + return ((stepCount * (2 * (circleRadius + (circleStrokeWidth / 2)))) + + ((stepCount - 1) * (lineLengthComputed + (lineGap * 2))) + extraWidth).toInt() } - - override fun getSuggestedMinimumHeight(): Int { var labelHeight = 0.0f - for(item in statusData){ - labelHeight = Math.max(labelHeight,setLabelsHeight(mTextPaintStatus,item)) + for (item in statusData) { + labelHeight = Math.max(labelHeight, setLabelsHeight(mTextPaintStatus, item)) } - if(statusData.size>0){ - labelHeight+=statusTopMargin + if (statusData.size > 0) { + labelHeight += statusTopMargin } - val circleRadius = if(isShowingCurrentStatus()) currentStatusRadius else circleRadius - return (((circleRadius * 2)+circleStrokeWidth) + labelHeight).toInt() + val circleRadius = if (isShowingCurrentStatus()) currentStatusRadius else circleRadius + return (((circleRadius * 2) + circleStrokeWidth) + labelHeight).toInt() } @@ -642,9 +636,9 @@ class StatusView @JvmOverloads constructor( val desiredWidth = paddingLeft + paddingRight + suggestedMinimumWidth val desiredHeight = paddingTop + paddingBottom + suggestedMinimumHeight - /* val measureSpecWidth = MeasureSpec.getMode(widthMeasureSpec) - val measureSpecHeight = MeasureSpec.getMode(heightMeasureSpec) - *//*if(measureSpecHeight!=MeasureSpec.AT_MOST || measureSpecWidth!=MeasureSpec.AT_MOST){ + /* val measureSpecWidth = MeasureSpec.getMode(widthMeasureSpec) + val measureSpecHeight = MeasureSpec.getMode(heightMeasureSpec) + *//*if(measureSpecHeight!=MeasureSpec.AT_MOST || measureSpecWidth!=MeasureSpec.AT_MOST){ throw IllegalStateException("Width and height should be wrap_content") }*//* */ @@ -655,7 +649,7 @@ class StatusView @JvmOverloads constructor( } override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { - setDrawingDimensions() + setDrawingDimensions() } override fun onDraw(canvas: Canvas?) { @@ -686,7 +680,7 @@ class StatusView @JvmOverloads constructor( } if (item.labelData != null) { - if (item.labelData.staticLayout!=null) { + if (item.labelData.staticLayout != null) { canvas?.save() canvas?.translate(item.labelData.x, item.labelData.y) @@ -715,37 +709,37 @@ class StatusView @JvmOverloads constructor( val lastPoint = PointF()//For keeping reference where last point was drawn lastPoint.x = paddingLeft.toFloat() + (circleStrokeWidth / 2) lastPoint.y = paddingTop.toFloat() + (circleRadius + (circleStrokeWidth / 2)) - if(isShowingCurrentStatus()) lastPoint.y += currentStatusRadius-circleRadius + if (isShowingCurrentStatus()) lastPoint.y += currentStatusRadius - circleRadius for (pos in 0 until stepCount) { var circleStrokePaint: Paint? - var circleFillPaint : Paint? - var textPaintLabel : TextPaint - var linePaint : Paint + var circleFillPaint: Paint? + var textPaintLabel: TextPaint + var linePaint: Paint var itemDrawable: Drawable? var circleRadius = this.circleRadius - if(isShowingCurrentStatus() && pos==(currentCount-1)){ + if (isShowingCurrentStatus() && pos == (currentCount - 1)) { circleRadius = currentStatusRadius circleStrokePaint = mCircleStrokePaintCurrent circleFillPaint = mCircleFillPaintCurrent textPaintLabel = mTextPaintLabelCurrent linePaint = mLinePaintCurrent itemDrawable = currentDrawable - }else if (isShowingIncompleteStatus() && pos in (currentCount)..stepCount) { + } else if (isShowingIncompleteStatus() && pos in (currentCount)..stepCount) { circleStrokePaint = mCircleStrokePaintIncomplete circleFillPaint = mCircleFillPaintIncomplete textPaintLabel = mTextPaintLabelsIncomplete linePaint = mLinePaintIncomplete itemDrawable = incompleteDrawable - }else{ + } else { - circleStrokePaint = this.mCircleStrokePaint - circleFillPaint = this.mCircleFillPaint - textPaintLabel = this.mTextPaintLabels - linePaint = this.mLinePaint - itemDrawable = completeDrawable + circleStrokePaint = this.mCircleStrokePaint + circleFillPaint = this.mCircleFillPaint + textPaintLabel = this.mTextPaintLabels + linePaint = this.mLinePaint + itemDrawable = completeDrawable } @@ -754,23 +748,23 @@ class StatusView @JvmOverloads constructor( var labelItemText: StatusView.StatusItemText? = null - if(pos==0){ - if(statusData.size>0){ - lastPoint.x+= Math.max(0.0f, (statusData[0].width - minStatusWidthExtremes(pos))/2) + if (pos == 0) { + if (statusData.size > 0) { + lastPoint.x += Math.max(0.0f, (statusData[0].width - minStatusWidthExtremes(pos)) / 2) } - }else{ + } else { lastPoint.x += lineGap lineItem = LineItem(PointF(lastPoint.x, lastPoint.y), PointF(lastPoint.x + lineLengthComputed, lastPoint.y), linePaint) - lastPoint.x = lineItem.end.x + lineGap + (circleStrokeWidth / 2) + lastPoint.x = lineItem.end.x + lineGap + (circleStrokeWidth / 2) } val circleItem = CircleItem(PointF((lastPoint.x + circleRadius), lastPoint.y), circleRadius, circleStrokePaint, circleFillPaint) lastPoint.x += ((circleRadius) * 2.0f) + (circleStrokeWidth / 2) - if(posminStatusWidthWidestPos){ + if (widestLineData.widestStatus.width > minStatusWidthWidestPos) { lineLengthComputed += widestLineData.widestStatus.width - minStatusWidthWidestPos } widestLineData.subordinateWidestStatus?.run { - //in case increasing linelength as per widest Status does not satisfy statusWidth for second widest - //This can occur if widestStatus belongs to currentStatus and has a zoomed radius + //in case increasing linelength as per widest Status does not satisfy statusWidth for second widest + //This can occur if widestStatus belongs to currentStatus and has a zoomed radius val minStatusWidth = minStatusWidth(pos) if (width > minStatusWidth) { @@ -889,37 +883,37 @@ class StatusView @JvmOverloads constructor( else -> item.width = widestLineData.widestStatus.width } - if(minStatusAdjacentMargin> 0 && !addMinStatusMargin && pos in 1 until statusData.size){ - if(minStatusWidth(pos)+ minStatusWidth(pos-1) - (item.width+statusData[pos-1].width) 0 && !addMinStatusMargin && pos in 1 until statusData.size) { + if (minStatusWidth(pos) + minStatusWidth(pos - 1) - (item.width + statusData[pos - 1].width) < minStatusAdjacentMargin) { addMinStatusMargin = true } } } - if(addMinStatusMargin){ + if (addMinStatusMargin) { //add additional padding only if it is required - lineLengthComputed+= minStatusAdjacentMargin + lineLengthComputed += minStatusAdjacentMargin } return extraWidth } - private fun minStatusWidth(pos:Int): Float { + private fun minStatusWidth(pos: Int): Float { var circleRadius = this.circleRadius - val lineWidth = (lineLengthComputed + lineGap*2) + val lineWidth = (lineLengthComputed + lineGap * 2) - if(isShowingCurrentStatus() && pos==currentCountIndex()){ + if (isShowingCurrentStatus() && pos == currentCountIndex()) { circleRadius = currentStatusRadius } - return (2 * circleRadius + circleStrokeWidth) + lineWidth + return (2 * circleRadius + circleStrokeWidth) + lineWidth } - private fun minStatusWidthExtremes(pos:Int): Float { + private fun minStatusWidthExtremes(pos: Int): Float { var circleRadius = this.circleRadius - if(isShowingCurrentStatus() && pos==currentCountIndex()){ + if (isShowingCurrentStatus() && pos == currentCountIndex()) { circleRadius = currentStatusRadius } return (2 * circleRadius + circleStrokeWidth) @@ -928,7 +922,7 @@ class StatusView @JvmOverloads constructor( /** * Maximum width that a text would need to be drawn */ - private fun getTextWidth(paint:Paint, text:String):Float{ + private fun getTextWidth(paint: Paint, text: String): Float { return paint.measureText(text) } @@ -938,12 +932,12 @@ class StatusView @JvmOverloads constructor( * @param labelInfo LabelInfo which contains width and text * @return Height that the label would require */ - private fun setLabelsHeight(textPaint:TextPaint, labelInfo: StatusInfo):Float{ + private fun setLabelsHeight(textPaint: TextPaint, labelInfo: StatusInfo): Float { val staticLayoutHeight = getStaticLayout(labelInfo.text, textPaint, labelInfo.width) labelInfo.staticLayout = staticLayoutHeight - labelInfo.height = staticLayoutHeight.height.toFloat() + labelInfo.height = staticLayoutHeight.height.toFloat() return labelInfo.height - } + } /** @@ -968,15 +962,15 @@ class StatusView @JvmOverloads constructor( * @param extremeLeftStatusWidth Widest line in status at extreme left * @param extremeRightStatusWidth Widest line in status at extreme right */ - class StatusTextWidthInfo(var widestStatus:StatusWidth, var subordinateWidestStatus:StatusWidth?=null, - var extremeLeftStatusWidth:Float=0.0f, var extremeRightStatusWidth:Float=0.0f) + class StatusTextWidthInfo(var widestStatus: StatusWidth, var subordinateWidestStatus: StatusWidth? = null, + var extremeLeftStatusWidth: Float = 0.0f, var extremeRightStatusWidth: Float = 0.0f) /** * Stores Status Width Data * @param width widestStatus * @param pos Status position */ - class StatusWidth(var width: Float = 0.0f, var pos:Int=-1) + class StatusWidth(var width: Float = 0.0f, var pos: Int = -1) /** * Calculates parameters described in StatusTextWidthInfo @@ -984,7 +978,7 @@ class StatusView @JvmOverloads constructor( * @param paint Paint required to draw the statuses * */ - private fun getStatusTextWidthInfo(list:List, paint:TextPaint):StatusTextWidthInfo{ + private fun getStatusTextWidthInfo(list: List, paint: TextPaint): StatusTextWidthInfo { val widestStatus = StatusWidth() var subordinateWidestStatus: StatusWidth? = null @@ -1014,7 +1008,7 @@ class StatusView @JvmOverloads constructor( } when (pos) { - 0 -> statusWidthInfo.extremeLeftStatusWidth= result + 0 -> statusWidthInfo.extremeLeftStatusWidth = result stepCountIndex() -> statusWidthInfo.extremeRightStatusWidth = result } @@ -1032,13 +1026,13 @@ class StatusView @JvmOverloads constructor( * @param paint Text paint for the text * @return widest line in a particular status */ - private fun getStatusWidth(text:String, paint: TextPaint):Float{ + private fun getStatusWidth(text: String, paint: TextPaint): Float { - val arr:List = text.split('\n') + val arr: List = text.split('\n') var result = 0.0f - for(sub in arr){ + for (sub in arr) { val subWidth = paint.measureText(sub) - result = if(subWidth>result) subWidth else result + result = if (subWidth > result) subWidth else result } return result @@ -1060,21 +1054,21 @@ class StatusView @JvmOverloads constructor( /** * actual position in list for currentCount */ - private fun currentCountIndex() = currentCount-1 + private fun currentCountIndex() = currentCount - 1 /** * actual position in list for stepCount */ - private fun stepCountIndex() = stepCount-1 + private fun stepCountIndex() = stepCount - 1 /** * Delegate property used to requestLayout on value set after executing a custom function */ - inner class OnLayoutProp (private var field:T, private inline var func:()->Unit={}){ - operator fun setValue(thisRef: Any?,p: KProperty<*>,v: T) { + inner class OnLayoutProp(private var field: T, private inline var func: () -> Unit = {}) { + operator fun setValue(thisRef: Any?, p: KProperty<*>, v: T) { field = v - if(ViewCompat.isLaidOut(this@StatusView)){ + if (ViewCompat.isLaidOut(this@StatusView)) { drawingData.clear() func() requestLayout() @@ -1082,7 +1076,8 @@ class StatusView @JvmOverloads constructor( } } - operator fun getValue(thisRef: Any?,p: KProperty<*>):T{ + + operator fun getValue(thisRef: Any?, p: KProperty<*>): T { return field } @@ -1091,29 +1086,30 @@ class StatusView @JvmOverloads constructor( /** * Delegate Property used to invalidate on value set after executing a custom function */ - inner class OnValidateProp (private var field:T, private inline var func:()->Unit={}){ - operator fun setValue(thisRef: Any?,p: KProperty<*>,v: T) { + inner class OnValidateProp(private var field: T, private inline var func: () -> Unit = {}) { + operator fun setValue(thisRef: Any?, p: KProperty<*>, v: T) { field = v - if(ViewCompat.isLaidOut(this@StatusView)){ + if (ViewCompat.isLaidOut(this@StatusView)) { func() invalidate() } } - operator fun getValue(thisRef: Any?,p: KProperty<*>):T{ + + operator fun getValue(thisRef: Any?, p: KProperty<*>): T { return field } } - private fun Float.pxValue(unit:Int = TypedValue.COMPLEX_UNIT_DIP):Float{ - return TypedValue.applyDimension(unit,this,resources.displayMetrics) + private fun Float.pxValue(unit: Int = TypedValue.COMPLEX_UNIT_DIP): Float { + return TypedValue.applyDimension(unit, this, resources.displayMetrics) } fun getScrollPosForStep(count: Int): Int { val posIndex = count - 1 - return if (posIndex> 0 && posIndex < drawingData.size) { + return if (posIndex > 0 && posIndex < drawingData.size) { drawingData[posIndex].circleItem.center.x.toInt() } else { 0 From 778a816a4077778917e47f02d089a9f5e040e36a Mon Sep 17 00:00:00 2001 From: Parm Singh Date: Wed, 15 Aug 2018 18:31:30 +0530 Subject: [PATCH 03/11] master: sugess min height, width edge case fixed --- .../java/params/com/statusView/StatusView.kt | 54 +++++++++++++------ 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/params/com/statusView/StatusView.kt b/app/src/main/java/params/com/statusView/StatusView.kt index a8b0294..ac83ec8 100644 --- a/app/src/main/java/params/com/statusView/StatusView.kt +++ b/app/src/main/java/params/com/statusView/StatusView.kt @@ -596,6 +596,11 @@ class StatusView @JvmOverloads constructor( override fun getSuggestedMinimumWidth(): Int { + if (stepCount <= 0) { + return 0 + } + + lineLengthComputed = lineLength var extraWidth = if (strictObeyLineLength) {// extra width required by status at extreme positions setWidthDataForObeyingLineLength() @@ -603,32 +608,54 @@ class StatusView @JvmOverloads constructor( setWidthDataForObeyingStatusText() } + if (stepCount == 1) { + extraWidth *= 2 + } + if (isShowingCurrentStatus()) { extraWidth += (currentStatusRadius - circleRadius) * 2 } - if (stepCount == 1) { - extraWidth *= 2 - } - return ((stepCount * (2 * (circleRadius + (circleStrokeWidth / 2)))) + ((stepCount - 1) * (lineLengthComputed + (lineGap * 2))) + extraWidth).toInt() } override fun getSuggestedMinimumHeight(): Int { + if (stepCount <= 0) { + return 0 + } + + var maxLabelHeight = 0.0f - var labelHeight = 0.0f for (item in statusData) { - labelHeight = Math.max(labelHeight, setLabelsHeight(mTextPaintStatus, item)) + maxLabelHeight = Math.max(maxLabelHeight, setLabelsHeight(mTextPaintStatus, item)) } - if (statusData.size > 0) { - labelHeight += statusTopMargin + + val circleAndStatusTextHeight = if (isShowingCurrentStatus()) { + val topRadius = currentStatusRadius + val labelHeightCurrentStatus = if (statusData.size > 0 && currentCountIndex() in 0..statusData.size) { + statusData[currentCountIndex()].height + } else { + 0.0f + } + + val bottomRadiusAndText = Math.max(currentStatusRadius + labelHeightCurrentStatus, circleRadius + maxLabelHeight) + + topRadius + bottomRadiusAndText + + } else { + circleRadius * 2 + maxLabelHeight + } + + val statusTopMargin = if (statusData.size > 0) { + statusTopMargin + } else { + 0.0f } - val circleRadius = if (isShowingCurrentStatus()) currentStatusRadius else circleRadius - return (((circleRadius * 2) + circleStrokeWidth) + labelHeight).toInt() + return (circleAndStatusTextHeight + circleStrokeWidth + statusTopMargin).toInt() } @@ -636,12 +663,6 @@ class StatusView @JvmOverloads constructor( val desiredWidth = paddingLeft + paddingRight + suggestedMinimumWidth val desiredHeight = paddingTop + paddingBottom + suggestedMinimumHeight - /* val measureSpecWidth = MeasureSpec.getMode(widthMeasureSpec) - val measureSpecHeight = MeasureSpec.getMode(heightMeasureSpec) - *//*if(measureSpecHeight!=MeasureSpec.AT_MOST || measureSpecWidth!=MeasureSpec.AT_MOST){ - throw IllegalStateException("Width and height should be wrap_content") - }*//* -*/ val measuredWidth = resolveSize(desiredWidth, widthMeasureSpec) val measuredHeight = resolveSize(desiredHeight, heightMeasureSpec) @@ -841,6 +862,7 @@ class StatusView @JvmOverloads constructor( */ private fun setWidthDataForObeyingStatusText(): Float { var extraWidth = 0.0f + if (statusData.size == 0) return extraWidth val widestLineData: StatusTextWidthInfo = getStatusTextWidthInfo(statusData.map { it.text }, mTextPaintStatus) From 4ac5a6ee59dfb65ad72dbf94743950d85a083758 Mon Sep 17 00:00:00 2001 From: Parm Singh Date: Thu, 16 Aug 2018 01:20:51 +0530 Subject: [PATCH 04/11] master: bintray config added --- .idea/caches/build_file_checksums.ser | Bin 535 -> 585 bytes .idea/gradle.xml | 1 + .idea/misc.xml | 2 +- README.md | 2 +- app/build.gradle | 11 ++-- app/src/main/res/layout/activity_main.xml | 5 +- build.gradle | 12 +++- settings.gradle | 2 +- stepview/.gitignore | 1 + stepview/build.gradle | 59 ++++++++++++++++++ stepview/proguard-rules.pro | 21 +++++++ stepview/src/main/AndroidManifest.xml | 2 + .../java/params/com/stepview}/StatusView.kt | 8 +-- .../src/main/res/values/attrs.xml | 0 stepview/src/main/res/values/strings.xml | 3 + 15 files changed, 112 insertions(+), 17 deletions(-) create mode 100644 stepview/.gitignore create mode 100644 stepview/build.gradle create mode 100644 stepview/proguard-rules.pro create mode 100644 stepview/src/main/AndroidManifest.xml rename {app/src/main/java/params/com/statusView => stepview/src/main/java/params/com/stepview}/StatusView.kt (99%) rename {app => stepview}/src/main/res/values/attrs.xml (100%) create mode 100644 stepview/src/main/res/values/strings.xml diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index a016d0c7198ea2a0344e05149d54eba5b6c7d4d7..0527593ab078305ae84ab436db82a6b1f62a8fa8 100644 GIT binary patch delta 132 zcmV-~0DJ$J1jz)Dm;^tnkq(iZOaTXx=_wEsN$*0 - + diff --git a/README.md b/README.md index 2f210fe..b5522e0 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ An Android library written in kotlin to display steps (without any max-min limit * Stroke color (circle), fill color (circle), line color & label text color can be set differently for completed, current & incomplete states. ```XML - - - diff --git a/app/src/main/java/params/com/statusView/StatusView.kt b/stepview/src/main/java/params/com/stepview/StatusView.kt similarity index 99% rename from app/src/main/java/params/com/statusView/StatusView.kt rename to stepview/src/main/java/params/com/stepview/StatusView.kt index ac83ec8..2ee2d16 100644 --- a/app/src/main/java/params/com/statusView/StatusView.kt +++ b/stepview/src/main/java/params/com/stepview/StatusView.kt @@ -1,4 +1,4 @@ -package params.com.statusView +package params.com.stepview import android.content.Context import android.graphics.* @@ -764,9 +764,9 @@ class StatusView @JvmOverloads constructor( } - var lineItem: StatusView.LineItem? = null - var statusItemText: StatusView.LabelItemText? = null - var labelItemText: StatusView.StatusItemText? = null + var lineItem: LineItem? = null + var statusItemText: LabelItemText? = null + var labelItemText: StatusItemText? = null if (pos == 0) { diff --git a/app/src/main/res/values/attrs.xml b/stepview/src/main/res/values/attrs.xml similarity index 100% rename from app/src/main/res/values/attrs.xml rename to stepview/src/main/res/values/attrs.xml diff --git a/stepview/src/main/res/values/strings.xml b/stepview/src/main/res/values/strings.xml new file mode 100644 index 0000000..27ecf23 --- /dev/null +++ b/stepview/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + stepview + From d03cad2f6a01289ed7c8fc535e43f6855f6a23eb Mon Sep 17 00:00:00 2001 From: Parm Singh Date: Thu, 16 Aug 2018 04:07:07 +0530 Subject: [PATCH 05/11] master: Readme edit --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index b5522e0..b8dc0ca 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,12 @@ # StepViewAndroid An Android library written in kotlin to display steps (without any max-min limits) along with the status/description. It also supports some really cool features. +## Setup + +``` +implementation 'com.params.stepview:stepview:1.0.0' +``` + ## Usage ### A customised StepView From 423fd696f443b152f584ebb05019578219265a49 Mon Sep 17 00:00:00 2001 From: Parminder Singh Date: Fri, 19 Oct 2018 02:31:33 +0530 Subject: [PATCH 06/11] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index b8dc0ca..1e8aae9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ # StepViewAndroid An Android library written in kotlin to display steps (without any max-min limits) along with the status/description. It also supports some really cool features. +## Custom Views Tutorial +For any information on how to create custom views you can refer to the link below.
+https://medium.com/mindorks/how-to-create-custom-views-141dc0570e57 + ## Setup ``` From d3607610bfe5ee2dcd62693120a38a8e733dd169 Mon Sep 17 00:00:00 2001 From: Parm Singh Date: Fri, 26 Oct 2018 15:35:46 +0530 Subject: [PATCH 07/11] master: init paint incase of currentCountbug fix --- .idea/misc.xml | 2 +- stepview/src/main/java/params/com/stepview/StatusView.kt | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 99202cc..c0f68ed 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -25,7 +25,7 @@
- + diff --git a/stepview/src/main/java/params/com/stepview/StatusView.kt b/stepview/src/main/java/params/com/stepview/StatusView.kt index 2ee2d16..9c658ad 100644 --- a/stepview/src/main/java/params/com/stepview/StatusView.kt +++ b/stepview/src/main/java/params/com/stepview/StatusView.kt @@ -105,7 +105,9 @@ class StatusView @JvmOverloads constructor( /* The count up to which status has been completed */ - var currentCount: Int by OnLayoutProp(INVALID_STATUS_COUNT) + var currentCount: Int by OnLayoutProp(INVALID_STATUS_COUNT){ + initCirclePaints() + } /* From 87e82bde77b4f30ecfb322dbdcea5710f58ed4da Mon Sep 17 00:00:00 2001 From: Parm Singh Date: Wed, 31 Oct 2018 00:07:11 +0530 Subject: [PATCH 08/11] master: fixed changing props while viewcompat is being laid out --- .idea/misc.xml | 2 +- README.md | 10 ++++++++++ .../main/java/params/com/statusView/MainActivity.kt | 9 +++++++-- app/src/main/res/layout/activity_main.xml | 1 + .../src/main/java/params/com/stepview/StatusView.kt | 7 ++++--- 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index c0f68ed..99202cc 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -25,7 +25,7 @@ - + diff --git a/README.md b/README.md index 1e8aae9..8a92d02 100644 --- a/README.md +++ b/README.md @@ -94,3 +94,13 @@ implementation 'com.params.stepview:stepview:1.0.0' * The view can be scrolled if the content exceeds the available width. * You can also scroll to a particular step by calling ```statusViewScroller.scrollToStep(stepCount)``` + +### Changing properties at runtime + +* You can also easily change any property at runtime as described below. +``` + statusViewScroller.statusView.run { + currentCount = 2 + circleFillColorCurrent = Color.RED + } +``` diff --git a/app/src/main/java/params/com/statusView/MainActivity.kt b/app/src/main/java/params/com/statusView/MainActivity.kt index ae20a1f..3d0f202 100644 --- a/app/src/main/java/params/com/statusView/MainActivity.kt +++ b/app/src/main/java/params/com/statusView/MainActivity.kt @@ -1,7 +1,8 @@ package params.com.statusView -import android.support.v7.app.AppCompatActivity +import android.graphics.Color import android.os.Bundle +import android.support.v7.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { @@ -9,9 +10,13 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + statusViewScroller.statusView.run { + currentCount = 2 + circleFillColorCurrent = Color.RED + } + } - } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 424f945..e04780b 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -9,6 +9,7 @@ (private var field: T, private inline var func: () -> Unit = {}) { operator fun setValue(thisRef: Any?, p: KProperty<*>, v: T) { field = v - if (ViewCompat.isLaidOut(this@StatusView)) { + if (propsIntialisedOnce) { drawingData.clear() func() requestLayout() @@ -1113,7 +1114,7 @@ class StatusView @JvmOverloads constructor( inner class OnValidateProp(private var field: T, private inline var func: () -> Unit = {}) { operator fun setValue(thisRef: Any?, p: KProperty<*>, v: T) { field = v - if (ViewCompat.isLaidOut(this@StatusView)) { + if (propsIntialisedOnce) { func() invalidate() From 9b95ec0884df54d59ec1fca8b9995309e577f193 Mon Sep 17 00:00:00 2001 From: Parm Singh Date: Wed, 31 Oct 2018 00:25:39 +0530 Subject: [PATCH 09/11] master: version 1.0.1 released --- .idea/caches/build_file_checksums.ser | Bin 585 -> 585 bytes README.md | 2 +- stepview/build.gradle | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 0527593ab078305ae84ab436db82a6b1f62a8fa8..90e1a2d512f2520158561d7dd65be8c6da6fe8d6 100644 GIT binary patch delta 37 vcmV+=0NVe_1jz)Dmj!0VP=z3|oIwE)S$;>`g0NSq#$F__AgO2TlkEXqE(Z{z delta 37 tcmX@fa*}1jbk Date: Sun, 19 May 2019 16:09:54 +1200 Subject: [PATCH 10/11] setStatusList dynamic working fixed --- stepview/src/main/java/params/com/stepview/StatusView.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/stepview/src/main/java/params/com/stepview/StatusView.kt b/stepview/src/main/java/params/com/stepview/StatusView.kt index 04ee447..c684c2e 100644 --- a/stepview/src/main/java/params/com/stepview/StatusView.kt +++ b/stepview/src/main/java/params/com/stepview/StatusView.kt @@ -372,7 +372,11 @@ class StatusView @JvmOverloads constructor( */ fun setStatusList(list: List) { //to make sure original list is not modified convert to mutableList - val input = list.toMutableList().dropLast(stepCount) + val input = list.toMutableList() + if (stepCount > 0 && list.size - stepCount > 0) { + input.dropLast(list.size - stepCount) + } + statusData = (input.map { StatusInfo(it) }).toMutableList() @@ -638,7 +642,7 @@ class StatusView @JvmOverloads constructor( val circleAndStatusTextHeight = if (isShowingCurrentStatus()) { val topRadius = currentStatusRadius - val labelHeightCurrentStatus = if (statusData.size > 0 && currentCountIndex() in 0..statusData.size) { + val labelHeightCurrentStatus = if (statusData.size > 0 && currentCountIndex() in 0..(statusData.size-1)) { statusData[currentCountIndex()].height } else { 0.0f From 722ccb391100881ea32e695edc33aa3025176a5e Mon Sep 17 00:00:00 2001 From: Parm Singh Date: Tue, 21 May 2019 00:07:43 +1200 Subject: [PATCH 11/11] v1.0.2 release --- README.md | 2 +- stepview/build.gradle | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 59d1dbb..5186132 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ https://medium.com/mindorks/how-to-create-custom-views-141dc0570e57 ## Setup ``` -implementation 'com.params.stepview:stepview:1.0.1' +implementation 'com.params.stepview:stepview:1.0.2' ``` ## Usage diff --git a/stepview/build.gradle b/stepview/build.gradle index 22507e1..25ec01f 100644 --- a/stepview/build.gradle +++ b/stepview/build.gradle @@ -8,7 +8,7 @@ ext { publishedGroupId = 'com.params.stepview' libraryName = 'stepView' artifact = 'stepview' - libraryVersion = '1.0.1' + libraryVersion = '1.0.2' libraryDescription = 'An Android library written in kotlin to display steps (without any max-min limits) along with the status/description.' siteUrl = 'https://github.com/params-ing/StepViewAndroid' @@ -32,8 +32,8 @@ android { defaultConfig { minSdkVersion versions.minSdk targetSdkVersion versions.targetSdk - versionCode 1 - versionName "1.0.1" + versionCode 2 + versionName "1.0.2" } buildTypes {