This library allows to draw different shapes, lines, marks easily. It's customizable and provides posibility to fill your custom shapes by color, gradient or texture. Also you can fill just by stroke with color, gradient or texture. If you want to add some labels or marks on your shapes or lines it's not difficult with this toolbox.
Add it in your root build.gradle
at the end of repositories:
allprojects {
repositories {
// ... other repositories
maven { url "https://jitpack.io" }
}
}
Then add the dependencies that you need in your project.
dependencies {
compile 'com.github.gleb8k:Android-PathShapeView:1.3.2'
}
The main class to show your graphic items is PathShapeView You can create it and attach to your root view:
val pathShapeView = PathShapeView(context: Context)
...
Or inflate from xml:
<shape.path.view.PathShapeView
android:id="@+id/path"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
Use PathShape class to config graphic items
val pathShape = PathShape.create()
...
//or load from .json
val pathShape = PathShape.fromAsset(context, fileName)
...
pathShapeView.setPath(pathShape)
...
Or add assetShapeResource attribute to PathShapeView in xml
...
xmlns:app="http://schemas.android.com/apk/res-auto"
...
<shape.path.view.PathShapeView
android:id="@+id/path"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:assetShapeResource="pathShape.json">
...
Here is a sample of file format in json
-
PathProvider - is the main class which allow to create different graphic items. Each item can be added with the logical operation (PathOperation: ADD, SUB, SUB_REVERSE, JOIN, INTERSECT, XOR)
Just to simple add item use ADD operation. There are several items which you can create:- putLines(list: List, isClosed:Boolean, operation: PathOperation) - add lines by list of points, isClosed - allows to close the current contour.
- putArc(centerPoint: PointF, width:Float, height:Float, startAngle: Float, sweepAngle: Float, operation: PathOperation) - add arc to the path as a new contour
- putOval(centerPoint: PointF, width:Float, height:Float, operation: PathOperation) - add a closed oval contour
- putCircle(centerPoint: PointF, radius:Float, operation: PathOperation) - add a closed circle contour
- putPoly(centerPoint: PointF, radius:Float, angleRotation: Float, sidesCount:Int, operation: PathOperation) - add equilateral polygon
- putStar(centerPoint: PointF, outerRadius:Float, innerRadius: Float, angleRotation: Float, sidesCount:Int, operation: PathOperation) - add star shape
- putRect(centerPoint: PointF, width:Float, height:Float, operation: PathOperation) - add a closed rectangle contour
- putRoundRect(centerPoint: PointF, width:Float, height:Float, cornerRadius: Float, operation: PathOperation) - add a closed round-rectangle contour
- putText(centerPoint: PointF, width: Float, height: Float, text: String, textConfigurator: TextConfigurator, operation: PathOperation) - add text
- putCustomShape(customLinesBuilder: CustomLinesBuilder, operation: PathOperation) - add customLinesBuilder object
-
CustomLinesBuilder - class which helps to create custom lines by points or by function
- addPoint(x: Float, y: Float) - add new point
- addGraphPoints(minX: Float, maxX: Float, minY: Float, maxY: Float, function: GraphFunction) - add points created by function and limited by bounds: minX, maxX, minY, maxY.
- setClosed(isClosed: Boolean) - close the current contour
-
GraphFunction - abstract class which provide function
- onFunctionGetValue(xValue: Float, stepValue: Float, maxStepCount: Int): Float - return function value
- offset(dx: Float, dy: Float) - offset current point by distance
- rotate(angle: Float) - rotate current point by angle
- skew(kx: Float, ky: Float) - skew current point by coefficients
-
WaveFunction(var waveWidth: Float, var waveHeight: Float, var waveType: WaveType) - class allows to create wave function by waveType(SINE, SINE_ARC, SINE_ARC_REVERSE, SQUARE, TRIANGLE, SAWTOOTH)
-
BodyFillProvider - class which allows to fill your graphic items. There are methods of BodyFillProvider:
- setColor(color: Int) - set the fill color
- setGradient(gradient: GradientProvider) - set the fill gradient. There are methods of GradientProvider:
- gradient.setType(type: Type) - gradient can be(LINEAR, RADIAL or SWEEP)
- gradient.setAngle(angle: Float) - set the angle of gradient direction
- gradient.setLength(length: Float) - set the length of gradient, by default it fills fit view size
- gradient.setStartPoint(startPoint: PointF) - set the start position of gradient
- gradient.addColor(color: Int) - add new color to gradient
- gradient.addColor(color: Int, colorPosition: Float) - add new color to gradient with color position, colorPosition can be in [0..1]
- setTexture(resId: Int) - set the fill texture by resource id
- setTexture(bitmap: Bitmap) - set the fill texture by bitmap
- fitTextureToSize(width: Float, height: Float) - fit texture to current size
- fitTextureToSize(width: Float, height: Float, convertWithPointConverter: Boolean) - fit texture to current size with possibility to convert setted size
- setFillType(fillType: FillType) - set fill type for gradient or texture (REPEAT, MIRROR, CLAMP)
- setRoundedCorners(radius: Float) - set all corners rounded with radius
- setGlowEffect(radius: Float, glowType: GlowType) - set the glow effect with radius and type (NORMAL, SOLID, OUTER, INNER)
- setEmbossEffect(angle: Float, embossType: EmbossType) - set the emboss effect with angle of direction and type (EMBOSS, EXTRUDE)
- setShadow(radius: Float, dx: Float, dy: Float, color: Int) - draws a shadow, with the specified offset and color, and blur radius.
-
ContourFillProvider - class which allows to draw the contour of your graphic items. Has the same methods with the BodyFillProvider class and several specified methods:
- setWidth(width: Float) - set the width of contour
- setIsDotRounded(isDotRounded: Boolean) - if your contour is dashed it allows to round your dots
- addDotParams(dotLength: Float, dotDistance: Float) - set your contour is dashed and add dot params. You can add params more than one time. Each new params will configure the next dot.
-
list of Mark items - marks which show labels and icons on the graphic items. Each mark can be configured by the following methods:
- addPosition(point: PointF) - add new position to current mark
- addPosition(point: PointF, label: String?) - add new position with label to current mark
- addPositions(points: List) - add list of positions to current mark
- addPositions(points: List, labels: List) - add list of positions and list of labels to current mark
- setDrawable(resId: Int) - set image resource to current mark
- setDrawable(drawable: Drawable) - set image drawable to current mark
- fitDrawableToSize(width: Float, height: Float) - scale mark icon to current size
- setTextConfigurator(configurator: TextConfigurator) - set text configuration to mark. It does effect when mark contains text labels.
-
TextConfigurator - main class to configure text params. There are following methods:
- setStyle(vararg style: Style) - set text style(BOLD, UNDERLINE, STRIKE, SUB_PIXEL, ITALIC)
- setTextSize(size: Float) - set text size
- setTextColor(color: Int) - set text color
- setTypeface(typeface: Typeface) set text font
- setTextOffset(offset: PointF) set text offset position
-
PointConverter - main class which allows convert positions of graphic items. There are 3 types of PointConverter:
- DefaultPointConverter - doesn't convert any positions
- PercentagePointConverter - convert all points with percantage aspect ratio to view size. Positions can be in [0..1]. If position is out of range converted position will be out of view size.
- CoordinateConverter - convert all positions from old view bounds(width and height) with aspect ratio to current view size
Set OnMarkClickListener to view
PathShape contains of:
pathShapeView.setOnMarkClickListener(object : PathShapeView.OnMarkClickListener {
override fun onMarkClick(markId: Int, markItem: MarkItem) {
//To change body of created functions use File | Settings | File Templates.
}
})
- Sample for drawing shapes
Draw triangle with rounded corners:
var list = arrayListOf<PathShape>()
var pathProvider = PathProvider()
var points = ArrayList<PointF>()
points.add(PointF(0.1f, 0.9f))
points.add(PointF(0.5f, 0.1f))
points.add(PointF(0.9f, 0.9f))
pathProvider.putLines(points, true, PathProvider.PathOperation.ADD)
var body = BodyFillProvider()
body.setColor(Color.GRAY)
body.setRoundedCorners(30f)
var contour = ContourFillProvider()
contour.setColor(Color.BLACK)
contour.setWidth(10f)
contour.setRoundedCorners(30f)
var pathShape = PathShape.create()
.setPath(pathProvider)
.fillBody(body)
.fillContour(contour)
.setPointConverter(PercentagePointConverter())
Draw rect
...
pathProvider.putRect(PointF(0.5f, 0.5f), 0.9f, 0.9f, PathProvider.PathOperation.ADD)
...
Draw oval
...
pathProvider.putOval(PointF(0.5f, 0.5f), 0.9f, 0.9f, PathProvider.PathOperation.ADD)
...
Draw arc
...
pathProvider.putArc(PointF(0.5f, 0.5f), 0.9f, 0.7f, 30f, 230f, PathProvider.PathOperation.ADD)
...
- Dashed contour sample
val pathProvider = PathProvider()
pathProvider.putRect(PointF(0.5f, 0.5f), 0.9f, 0.9f, PathProvider.PathOperation.ADD)
val contour = ContourFillProvider()
contour.setColor(Color.BLACK)
contour.setWidth(20f)
contour.addDotParams(20f, 40f)
contour.addDotParams(40f, 40f)
contour.addDotParams(40f, 40f)
contour.setIsDotRounded(true)
...
- Shape with gradient sample
var pathProvider = PathProvider()
pathProvider.putRoundRect(PointF(0.5f, 0.5f), 0.9f, 0.9f, 0.2f, PathProvider.PathOperation.ADD)
var gradient = GradientProvider()
gradient.addColor(Color.BLUE)
.addColor(Color.WHITE)
.addColor(Color.BLUE)
.setType(GradientProvider.Type.SWEEP)
var body = BodyFillProvider()
body.setGradient(gradient)
gradient = GradientProvider()
gradient.addColor(Color.BLACK, 0f)
.addColor(Color.RED,0.1f)
.addColor(Color.WHITE,0.5f)
.addColor(Color.RED,0.9f)
.addColor(Color.BLACK,1f)
.setType(GradientProvider.Type.LINEAR)
var contour = ContourFillProvider()
contour.setGradient(gradient)
contour.setWidth(100f)
...
- Logical operations with shapes
var pathProvider = PathProvider()
pathProvider.putRect(PointF(0.5f, 0.5f), 0.9f, 0.9f, PathProvider.PathOperation.ADD)
pathProvider.putOval(PointF(0.5f, 0.5f), 0.6f, 1f, PathProvider.PathOperation.JOIN)
pathProvider.putOval(PointF(0.5f, 0.5f), 1f, 0.6f, PathProvider.PathOperation.JOIN)
var contour = ContourFillProvider()
contour.setColor(Color.BLACK)
contour.setWidth(20f)
var body = BodyFillProvider()
body.setColor(Color.LTGRAY)
...
...
pathProvider.putRect(PointF(0.5f, 0.5f), 0.9f, 0.9f, PathProvider.PathOperation.ADD)
pathProvider.putOval(PointF(0.5f, 0.5f), 0.6f, 1f, PathProvider.PathOperation.INTERSECT)
pathProvider.putOval(PointF(0.5f, 0.5f), 1f, 0.6f, PathProvider.PathOperation.INTERSECT)
...
...
pathProvider.putRect(PointF(0.5f, 0.5f), 0.9f, 0.9f, PathProvider.PathOperation.ADD)
pathProvider.putOval(PointF(0.5f, 0.5f), 0.6f, 1f, PathProvider.PathOperation.SUB)
pathProvider.putOval(PointF(0.5f, 0.5f), 1f, 0.6f, PathProvider.PathOperation.SUB)
...
...
pathProvider.putRect(PointF(0.5f, 0.5f), 0.9f, 0.9f, PathProvider.PathOperation.ADD)
pathProvider.putOval(PointF(0.5f, 0.5f), 0.6f, 0.9f, PathProvider.PathOperation.SUB_REVERSE)
pathProvider.putOval(PointF(0.5f, 0.5f), 0.9f, 0.6f, PathProvider.PathOperation.SUB_REVERSE)
...
- Sample with marks
var points = ArrayList()
points.add(PointF(0.1f, 0.1f))
points.add(PointF(0.5f, 0.3f))
points.add(PointF(0.6f, 0.4f))
points.add(PointF(0.7f, 0.6f))
points.add(PointF(0.9f, 0.8f))
var pathProvider = PathProvider()
pathProvider.putLines(points, false, PathProvider.PathOperation.ADD)
var contour = ContourFillProvider()
contour.setColor(Color.BLACK)
contour.setWidth(20f)
var mark = Mark()
mark.setDrawable(R.mipmap.ic_launcher)
mark.fitDrawableToSize(50f,50f)
var tc = TextConfigurator()
tc.setTextColor(Color.BLUE)
tc.setStyle(TextConfigurator.Style.BOLD, TextConfigurator.Style.UNDERLINE)
tc.setTextSize(20f)
tc.setTextOffset(PointF(0f, -30f))
mark.setTextConfigurator(tc)
points.forEach { mark.addPosition(it, it.toString()) }
var pathShape = PathShape.create()
.setPath(pathProvider)
.fillContour(contour)
.addMark(mark)
.setPointConverter(PercentagePointConverter()
- Text sample
var pathProvider = PathProvider()
var tc = TextConfigurator()
tc.setStyle(TextConfigurator.Style.BOLD, TextConfigurator.Style.ITALIC)
pathProvider.putText(PointF(0.5f, 0.5f), 0.5f, 0.2f,"Hello!", tc, PathProvider.PathOperation.ADD)
...
- Sample with effects
...
contour.setGlowEffect(30f, FillProvider.GlowType.SOLID)
...
Emboss effect
body.setEmbossEffect(45f, FillProvider.EmbossType.NORMAL)
Shadow
contour.setShadow(15f, 10f, 10f, Color.BLACK)
- Sample with list of custom wave shapes
val pathProvider = PathProvider()
val f = WaveFunction(0.2f, 0.1f, WaveType.SINE)
f.offset(0f, 0.85f)
val shape = CustomLinesBuilder()
shape.addGraphPoints( 0f, 1f, -1f, 1f, f)
shape.addPoint(1f, 0f)
shape.addPoint(0f, 0f)
shape.setClosed(true)
pathProvider.putCustomShape(shape, PathProvider.PathOperation.ADD)
...
Copyright (c) 2018 gleb8k
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.