I have a custom View in a Relative layout:
<my.app.com.GardenCalendarView
android:id="@ id/gardenCalendar"
android:layout_width="match_parent"
android:layout_height="84dp"
/>
which draws a calendar.
GardenCalendarView.java :
public class GardenCalendarView extends View {
private Plant plant;
private Rect bounds;
private Paint boundPaint;
private Paint subLinePaint;
private Paint textPaint;
private Paint barPaint;
private RectF startInsideRect;
private RectF transplantRect;
private RectF sowOutsideRect;
private static final int MARGIN = 40;
private static final int PADDING = 5;
private float partWidth;
public GardenCalendarView(Context context) {
super(context);
init(context);
}
public GardenCalendarView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public GardenCalendarView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public void setPlant(Plant plant) {
this.plant = plant;
invalidate();
}
public void init(Context context) {
bounds = new Rect();
boundPaint = new Paint();
boundPaint.setColor(Color.parseColor("#5E8364"));
boundPaint.setStyle(Paint.Style.STROKE);
boundPaint.setAntiAlias(true);
boundPaint.setStrokeWidth(1);
boundPaint.setStrokeJoin(Paint.Join.ROUND);
boundPaint.setStrokeCap(Paint.Cap.ROUND);
subLinePaint = new Paint(boundPaint);
subLinePaint.setColor(Color.parseColor("#B8CCBB"));
textPaint = new Paint(boundPaint);
textPaint.setColor(Color.DKGRAY);
textPaint.setTextSize(Utils.dpToPx(10f, context));
startInsideRect = new RectF();
transplantRect = new RectF();
sowOutsideRect = new RectF();
barPaint = new Paint();
barPaint.setAntiAlias(true);
barPaint.setStyle(Paint.Style.FILL_AND_STROKE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (plant != null) {
paint(canvas);
}
}
private void paint(Canvas canvas) {
canvas.drawRect(bounds, boundPaint);
// draw vertical lines
for (int i = 0; i < 36; i) {
if (i % 3 == 0) {
canvas.drawLine(
bounds.left partWidth * i,
bounds.top,
bounds.left partWidth * i,
bounds.bottom, boundPaint
);
//Paint month label
canvas.drawText(
Plant.MONTHS[i / 3],
bounds.left 10 partWidth * i,
bounds.top - 8, textPaint);
} else {
canvas.drawLine(
bounds.left partWidth * i,
bounds.top,
bounds.left partWidth * i,
bounds.bottom, subLinePaint);
}
}
// draw start inside bar
barPaint.setColor(plant.startInside.color);
canvas.drawRect(startInsideRect, barPaint);
// draw transplant bar
barPaint.setColor(plant.transplant.color);
canvas.drawRect(transplantRect, barPaint);
// draw sow outside bar
barPaint.setColor(plant.sowOutside.color);
canvas.drawRect(sowOutsideRect, barPaint);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
int xpad = getPaddingLeft() getPaddingRight();
int ypad = getPaddingTop() getPaddingBottom();
int ww = w - xpad;
int hh = h - ypad;
bounds.set(0, 0, ww, hh);
Utils.reduceRectBy(bounds, MARGIN);
partWidth = bounds.width() / 36f;
float partHeight = bounds.height() / 3f;
float monthWidth = partWidth * 1; //partWidth * 3; if full month column
startInsideRect.set(
bounds.left (plant.startInside.startMonth - 1) * monthWidth,
bounds.top 0 * partHeight PADDING,
bounds.left (plant.startInside.endMonth ) * monthWidth, //(plant.startInside.endMonth - 1) * monthWidth,
bounds.top 1 * partHeight - PADDING
);
transplantRect.set(
bounds.left (plant.transplant.startMonth - 1) * monthWidth,
bounds.top 1 * partHeight PADDING,
bounds.left (plant.transplant.endMonth ) * monthWidth,
bounds.top 2 * partHeight - PADDING
);
sowOutsideRect.set(
bounds.left (plant.sowOutside.startMonth - 1) * monthWidth,
bounds.top 2 * partHeight PADDING,
bounds.left (plant.sowOutside.endMonth ) * monthWidth,
bounds.top 3 * partHeight - PADDING
);
}
}
and then Plant.java:
public class Plant {
public String name;
public Bar startInside;
public Bar transplant;
public Bar sowOutside;
public static String[] MONTHS = new String[]{
"JAN", "FEB", "MAR", "APR", "MÁJ", "JÚN",
"JÚL", "AUG", "SEP", "OKT", "NOV", "DEC"
};
public Plant(String name, Bar startInside, Bar transplant, Bar sowOutside) {
this.name = name;
this.startInside = startInside;
this.transplant = transplant;
this.sowOutside = sowOutside;
}
}
and Bar.java:
public class Bar {
public int startMonth;
public int endMonth;
public int color;
public Bar(int start, int end, String color) {
this.startMonth = start;
this.endMonth = end;
this.color = Color.parseColor(color);
}
}
Now I am calling this to draw the calendar:
GardenCalendarView gardenCalendar = findViewById(R.id.gardenCalendar);
Bar startInsideBar = new Bar(5, 8, "#CCff8040");
Bar transplantBar = new Bar(9, 12, "#CC5E8364");
Bar sowOutsideBar = new Bar(15, 18, "#CCd2d200");
Plant myPlant = new Plant(
"plantName",
startInsideBar,
transplantBar,
sowOutsideBar);
gardenCalendar.setPlant(myPlant);
This is working fine, the View is shown.
But i have a button and after clicking on it, I want to redraw that View with another parameters.
public void ResetCalendar(View view)
{
GardenCalendarView gardenCalendar = findViewById(R.id.gardenCalendar);
gardenCalendar.invalidate();
Bar startInsideBar = new Bar(1, 5, "#CCff8040");
Bar transplantBar = new Bar(20, 25, "#CC5E8364");
Bar sowOutsideBar = new Bar(6, 8, "#CCd2d200");
Plant myPlant = new Plant(
"platName2",
startInsideBar,
transplantBar,
sowOutsideBar);
gardenCalendar.setPlant(myPlant);
}
You can see, only the numbers changed in the Bars, but nothing happens, the View has the old values and did not redraw. I tried also to call gardenCalendar.invalidate();
with no luck.
I also tried to call init
with context, but then the whole View disappeared and did not redraw.
CodePudding user response:
From the original question Android table as calendar view for whole year
Don't use the updated onSizeChanged
optimisation as it won't recalculate the position of the bars unless the size of view has changed.
If you had used different colours for the bars you would have noticed that they were redrawn in the new colours.
So your paint
method should look like
private void paint(Canvas canvas) {
getDrawingRect(bounds);
Utils.reduceRectBy(bounds, MARGIN);
canvas.drawRect(bounds, boundPaint);
float partWidth = bounds.width() / 36f;
// draw vertical lines
for (int i = 0; i< 36; i) {
if (i % 3 == 0) {
canvas.drawLine(
bounds.left partWidth *i,
bounds.top,
bounds.left partWidth *i,
bounds.bottom, boundPaint);
//Paint month label
String month = Plant.MONTHS[i/3].toString();
canvas.drawText(month, bounds.left partWidth *i, bounds.top - 4, textPaint);
} else {
canvas.drawLine(
bounds.left partWidth *i,
bounds.top,
bounds.left partWidth *i,
bounds.bottom, subLinePaint);
}
}
float partHeight = bounds.height() / 3f;
float monthWidth = partWidth*3;
// draw start inside bar
startInsideRect.left = bounds.left (plant.startInside.startMonth - 1)* monthWidth;
startInsideRect.right = bounds.left (plant.startInside.endMonth - 1)* monthWidth;
startInsideRect.top = bounds.top 0* partHeight PADDING;
startInsideRect.bottom = bounds.top 1* partHeight - PADDING;
barPaint.setColor(plant.startInside.color);
canvas.drawRect(startInsideRect, barPaint);
// draw transplant bar
transplantRect.left = bounds.left (plant.transplant.startMonth - 1)* monthWidth;
transplantRect.right = bounds.left (plant.transplant.endMonth - 1)* monthWidth;
transplantRect.top = bounds.top 1* partHeight PADDING;
transplantRect.bottom = bounds.top 2* partHeight - PADDING;
barPaint.setColor(plant.transplant.color);
canvas.drawRect(transplantRect, barPaint);
// draw sow outside bar
sowOutsideRect.left = bounds.left (plant.sowOutside.startMonth - 1)* monthWidth;
sowOutsideRect.right = bounds.left (plant.sowOutside.endMonth - 1)* monthWidth;
sowOutsideRect.top = bounds.top 2* partHeight PADDING;
sowOutsideRect.bottom = bounds.top 3* partHeight - PADDING;
barPaint.setColor(plant.sowOutside.color);
canvas.drawRect(sowOutsideRect, barPaint);
}
Also calling gardenCalendar.invalidate();
is unnecessary as it is done in setPlant