-
-
Save MehdiFal/36d0883632166a2b8e92211972f5dacb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<com.test.graphvisualizer.Graph | |
android:id="@+id/graph" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
app:layout_constraintBottom_toTopOf="parent" | |
app:layout_constraintBottom_toBottomOf="parent" | |
app:layout_constraintLeft_toLeftOf="parent" | |
app:layout_constraintRight_toRightOf="parent" | |
app:layout_constraintTop_toTopOf="parent" | |
android:paddingLeft="35dp" | |
android:paddingStart="35dp" | |
android:paddingRight="35dp" | |
android:paddingEnd="35dp" | |
android:paddingTop="100dp" | |
android:paddingBottom="100dp" | |
app:gradColorStart="@color/greenDark" | |
app:gradColorEnd="@color/greenLight" | |
app:markerColor="@color/greenDark" | |
app:connectedLinesColor="@color/greenDark" | |
app:guidelinesColor="@color/gray" | |
app:graduationColor="@color/gray" /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<resources> | |
<declare-styleable name="Graph"> | |
<attr name="gradColorStart" format="color"/> | |
<attr name="gradColorEnd" format="color"/> | |
<attr name="markerColor" format="color"/> | |
<attr name="connectedLinesColor" format="color"/> | |
<attr name="guidelinesColor" format="color"/> | |
<attr name="graduationColor" format="color"/> | |
</declare-styleable> | |
</resources> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Graph extends View { | |
private Paint paint; | |
private Paint gradientPaint; | |
private Paint connectionPaint; | |
private Path path; | |
private int markerColor; | |
private int connectedLinesColor; | |
private int guidelinesColor; | |
private int graduationColor; | |
private int graphHeight; | |
private int weeksCount; | |
private int weekWidth; | |
private int maxXGraduation; | |
private int maxYGraduation; | |
private List<Marker> markers; | |
public Graph (Context context) { | |
super (context); | |
init (context, null, 0, 0); | |
} | |
public Graph (Context context, @Nullable AttributeSet attrs) { | |
super (context, attrs); | |
init (context, attrs, 0, 0); | |
} | |
public Graph (Context context, @Nullable AttributeSet attrs, int defStyleAttr) { | |
super (context, attrs, defStyleAttr); | |
init (context, attrs, defStyleAttr, 0); | |
} | |
@RequiresApi (api = Build.VERSION_CODES.LOLLIPOP) | |
public Graph (Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { | |
super (context, attrs, defStyleAttr, defStyleRes); | |
init (context, attrs, defStyleAttr, defStyleRes); | |
} | |
private void init (Context context, AttributeSet attrs, int defStyle, int defStyleRes) { | |
paint = new Paint (Paint.ANTI_ALIAS_FLAG); | |
path = new Path (); | |
final TypedArray typedArray = context.obtainStyledAttributes (attrs, R.styleable.Graph, defStyle, defStyleRes); | |
int defaultColor = getResources ().getColor (R.color.colorPrimary); | |
markerColor = typedArray.getColor (R.styleable.Graph_markerColor, defaultColor); | |
connectedLinesColor = typedArray.getColor (R.styleable.Graph_connectedLinesColor, defaultColor); | |
guidelinesColor = typedArray.getColor (R.styleable.Graph_guidelinesColor, defaultColor); | |
graduationColor = typedArray.getColor (R.styleable.Graph_graduationColor, defaultColor); | |
int gradColorStart = typedArray.getColor (R.styleable.Graph_gradColorStart, defaultColor); | |
int gradColorEnd = typedArray.getColor (R.styleable.Graph_gradColorEnd, defaultColor); | |
LinearGradient gradient = new LinearGradient ( | |
getPaddingLeft (), | |
getPaddingTop (), | |
getPaddingRight (), | |
getHeight () - getPaddingBottom (), | |
new int[] { gradColorStart, gradColorEnd }, | |
null, | |
Shader.TileMode.CLAMP | |
); | |
gradientPaint = new Paint (Paint.ANTI_ALIAS_FLAG); | |
gradientPaint.setStyle (Paint.Style.FILL); | |
gradientPaint.setShader (gradient); | |
connectionPaint = new Paint (); | |
connectionPaint.setColor (connectedLinesColor); | |
connectionPaint.setStrokeWidth (3); | |
typedArray.recycle (); | |
} | |
@Override | |
protected void onDraw (Canvas canvas) { | |
super.onDraw (canvas); | |
if (markers == null) { | |
return; | |
} | |
drawSkeleton (canvas); | |
drawGraduations (canvas); | |
drawConnectPoints (canvas); | |
colorAreaBelowPoints (canvas); | |
} | |
private void drawSkeleton (Canvas canvas) { | |
// draw Y axis | |
weekWidth = (getWidth () - getPaddingLeft () - getPaddingRight ()) / weeksCount; | |
graphHeight = getHeight () - getPaddingTop () - getPaddingBottom (); | |
initSkeletonPaint (); | |
int maxY = getHeight () - getPaddingBottom (); | |
int x = getPaddingLeft (); | |
for (int i = 0; i < weeksCount; i ++) { | |
path.moveTo (x, getPaddingTop ()); | |
path.lineTo (x, maxY); | |
canvas.drawPath (path, paint); | |
path.reset (); | |
x += weekWidth; | |
} | |
path.reset (); | |
paint.reset (); | |
} | |
private void initSkeletonPaint () { | |
paint.setStyle (Paint.Style.STROKE); | |
paint.setStrokeWidth (2); | |
paint.setColor (guidelinesColor); | |
float [] interval = new float [graphHeight / 10]; | |
for (int i = 0; i < interval.length; i ++) { | |
interval [i] = 10; | |
} | |
paint.setPathEffect (new DashPathEffect (interval, 0f)); | |
} | |
private void drawGraduations (Canvas canvas) { | |
initGraduationsPaint (); | |
int x = getWidth () - getPaddingRight (); | |
float distY = (100f * graphHeight) / maxYGraduation; | |
float y = getHeight () - getPaddingBottom (); | |
for (int i = 0; i <= maxYGraduation; i += 100) { | |
canvas.drawText (String.valueOf (i), x, y, paint); | |
y -= distY; | |
} | |
path.reset (); | |
paint.reset (); | |
} | |
private void initGraduationsPaint () { | |
paint.setColor (graduationColor); | |
paint.setTextAlign (Paint.Align.LEFT); | |
paint.setTextSize (40); | |
} | |
private void drawConnectPoints (Canvas canvas) { | |
initPointsPaint (); | |
float distBetweenPoints = ((float) weekWidth) / 7; | |
float centerX = getPaddingLeft (); | |
float prevX = -1f; | |
float prevY = -1f; | |
for (Marker marker : markers) { | |
float centerY = (getHeight () - getPaddingBottom ()) - (marker.getValue () * graphHeight) / maxYGraduation; | |
if (prevX != -1f) { | |
canvas.drawLine (prevX, prevY, centerX, centerY, connectionPaint); | |
} | |
prevX = centerX; | |
prevY = centerY; | |
canvas.drawCircle (centerX, centerY, 7, paint); | |
centerX += distBetweenPoints; | |
} | |
paint.reset (); | |
} | |
private void initPointsPaint () { | |
paint.setStyle (Paint.Style.FILL); | |
paint.setStrokeWidth (5); | |
paint.setColor (markerColor); | |
} | |
private void colorAreaBelowPoints (Canvas canvas) { | |
path.moveTo (getPaddingLeft (), getHeight () - getPaddingBottom ()); | |
float centerX = getPaddingLeft (); | |
float distBetweenPoints = ((float) weekWidth) / 7; | |
for (Marker marker : markers) { | |
float centerY = (getHeight () - getPaddingBottom ()) - (marker.getValue () * graphHeight) / maxYGraduation; | |
path.lineTo (centerX, centerY); | |
centerX += distBetweenPoints; | |
} | |
float firstY = (getHeight () - getPaddingBottom ()) - (markers.get (0).getValue () * graphHeight) / maxYGraduation; | |
float lastX = centerX - distBetweenPoints; | |
path.lineTo (lastX, getHeight () - getPaddingBottom ()); | |
path.lineTo (getPaddingLeft (), firstY); | |
canvas.drawPath (path, gradientPaint); | |
path.reset (); | |
} | |
public void setData (List<Marker> markers) { | |
this.markers = markers; | |
int maxY = maxValue (markers); | |
maxXGraduation = markers.size () + 1; | |
maxYGraduation = ((maxY / 100) + 1) * 100; | |
for (Marker marker : markers) { | |
weeksCount = Math.max (weeksCount, marker.getWeek ()); | |
} | |
invalidate (); | |
} | |
private int maxValue (List<Marker> markers) { | |
int maxValue = 0; | |
for (Marker marker : markers) { | |
maxValue = Math.max (maxValue, marker.getValue ()); | |
} | |
return maxValue; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class MainActivity extends AppCompatActivity { | |
@Override | |
protected void onCreate (Bundle savedInstanceState) { | |
super.onCreate (savedInstanceState); | |
setContentView (R.layout.activity_main); | |
Graph graph = findViewById (R.id.graph); | |
graph.setData (markers ()); | |
} | |
private List<Marker> markers () { | |
List<Marker> markers = new ArrayList<> (); | |
markers.add (new Marker (0, 1, 1, 1)); | |
markers.add (new Marker (200, 2, 1, 1)); | |
markers.add (new Marker (100, 3, 1, 1)); | |
markers.add (new Marker (150, 4, 1, 1)); | |
markers.add (new Marker (50, 5, 1, 1)); | |
markers.add (new Marker (0, 6, 1, 1)); | |
markers.add (new Marker (350, 7, 1, 1)); | |
markers.add (new Marker (320, 1, 2, 1)); | |
markers.add (new Marker (320, 2, 2, 1)); | |
markers.add (new Marker (275, 3, 2, 1)); | |
markers.add (new Marker (0, 4, 2, 1)); | |
markers.add (new Marker (0, 5, 2, 1)); | |
markers.add (new Marker (200, 6, 2, 1)); | |
markers.add (new Marker (30, 7, 2, 1)); | |
markers.add (new Marker (550, 1, 3, 1)); | |
markers.add (new Marker (80, 2, 3, 1)); | |
markers.add (new Marker (110, 3, 3, 1)); | |
markers.add (new Marker (50, 4, 3, 1)); | |
markers.add (new Marker (50, 5, 3, 1)); | |
markers.add (new Marker (80, 6, 3, 1)); | |
markers.add (new Marker (50, 7, 3, 1)); | |
markers.add (new Marker (0, 1, 4, 1)); | |
markers.add (new Marker (30, 2, 4, 1)); | |
markers.add (new Marker (70, 3, 4, 1)); | |
markers.add (new Marker (110, 4, 4, 1)); | |
markers.add (new Marker (70, 5, 4, 1)); | |
markers.add (new Marker (0, 6, 4, 1)); | |
markers.add (new Marker (30, 7, 4, 1)); | |
markers.add (new Marker (70, 1, 5, 1)); | |
markers.add (new Marker (130, 2, 5, 1)); | |
markers.add (new Marker (250, 3, 5, 1)); | |
return markers; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Marker { | |
private int value; | |
private int day; | |
private int week; | |
private int month; | |
public Marker (int value, int day, int week, int month) { | |
this.value = value; | |
this.day = day; | |
this.week = week; | |
this.month = month; | |
} | |
public int getValue () { | |
return value; | |
} | |
public void setValue (int value) { | |
this.value = value; | |
} | |
public int getDay () { | |
return day; | |
} | |
public void setDay (int day) { | |
this.day = day; | |
} | |
public int getWeek () { | |
return week; | |
} | |
public void setWeek (int week) { | |
this.week = week; | |
} | |
public int getMonth () { | |
return month; | |
} | |
public void setMonth (int month) { | |
this.month = month; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment