package wangdaye.com.geometricweather.remoteviews.trend; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.widget.LinearLayout; import androidx.annotation.ColorInt; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.core.graphics.ColorUtils; import wangdaye.com.geometricweather.R; import wangdaye.com.geometricweather.basic.model.option.unit.TemperatureUnit; import wangdaye.com.geometricweather.basic.model.weather.Temperature; import wangdaye.com.geometricweather.utils.DisplayUtils; /** * Trend linear layout. * */ public class TrendLinearLayout extends LinearLayout { private Paint paint; private int[] historyTemps; private int[] historyTempYs; private int highestTemp; private int lowestTemp; private TemperatureUnit unit; @ColorInt private int lineColor; @ColorInt private int textColor; private float TREND_ITEM_HEIGHT; private float BOTTOM_MARGIN; private float TREND_MARGIN_TOP = 24; private float TREND_MARGIN_BOTTOM = 36; private float CHART_LINE_SIZE = 1; private float TEXT_SIZE = 10; private float MARGIN_TEXT = 2; public TrendLinearLayout(Context context) { super(context); this.initialize(); } public TrendLinearLayout(Context context, @Nullable AttributeSet attrs) { super(context, attrs); this.initialize(); } public TrendLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.initialize(); } private void initialize() { setWillNotDraw(false); this.paint = new Paint(); paint.setAntiAlias(true); paint.setStrokeCap(Paint.Cap.ROUND); paint.setTextSize(TEXT_SIZE); this.unit = TemperatureUnit.C; setColor(true); this.TREND_MARGIN_TOP = DisplayUtils.dpToPx(getContext(), (int) TREND_MARGIN_TOP); this.TREND_MARGIN_BOTTOM = DisplayUtils.dpToPx(getContext(), (int) TREND_MARGIN_BOTTOM); this.TEXT_SIZE = DisplayUtils.dpToPx(getContext(), (int) TEXT_SIZE); this.CHART_LINE_SIZE = DisplayUtils.dpToPx(getContext(), (int) CHART_LINE_SIZE); this.MARGIN_TEXT = DisplayUtils.dpToPx(getContext(), (int) MARGIN_TEXT); } @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); if (historyTemps == null) { return; } computeCoordinates(); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(CHART_LINE_SIZE); paint.setColor(lineColor); canvas.drawLine( 0, historyTempYs[0], getMeasuredWidth(), historyTempYs[0], paint ); canvas.drawLine( 0, historyTempYs[1], getMeasuredWidth(), historyTempYs[1], paint ); paint.setStyle(Paint.Style.FILL); paint.setTextSize(TEXT_SIZE); paint.setTextAlign(Paint.Align.LEFT); paint.setColor(textColor); canvas.drawText( Temperature.getShortTemperature(getContext(), historyTemps[0], unit), 2 * MARGIN_TEXT, historyTempYs[0] - paint.getFontMetrics().bottom - MARGIN_TEXT, paint ); canvas.drawText( Temperature.getShortTemperature(getContext(), historyTemps[1], unit), 2 * MARGIN_TEXT, historyTempYs[1] - paint.getFontMetrics().top + MARGIN_TEXT, paint ); paint.setTextAlign(Paint.Align.RIGHT); canvas.drawText( getContext().getString(R.string.yesterday), getMeasuredWidth() - 2 * MARGIN_TEXT, historyTempYs[0] - paint.getFontMetrics().bottom - MARGIN_TEXT, paint ); canvas.drawText( getContext().getString(R.string.yesterday), getMeasuredWidth() - 2 * MARGIN_TEXT, historyTempYs[1] - paint.getFontMetrics().top + MARGIN_TEXT, paint ); } // control. public void setColor(boolean lightTheme) { if (lightTheme) { lineColor = ColorUtils.setAlphaComponent(Color.BLACK, (int) (255 * 0.05)); textColor = ContextCompat.getColor(getContext(), R.color.colorTextSubtitle_light); } else { lineColor = ColorUtils.setAlphaComponent(Color.WHITE, (int) (255 * 0.1)); textColor = ContextCompat.getColor(getContext(), R.color.colorTextSubtitle_dark); } } public void setData(@Nullable int[] historyTemps, int highestTemp, int lowestTemp, TemperatureUnit unit, boolean daily) { this.historyTemps = historyTemps; this.highestTemp = highestTemp; this.lowestTemp = lowestTemp; this.unit = unit; if (daily) { this.TREND_ITEM_HEIGHT = DisplayUtils.dpToPx( getContext(), WidgetItemView.TREND_VIEW_HEIGHT_DIP_2X); this.BOTTOM_MARGIN = DisplayUtils.dpToPx( getContext(), WidgetItemView.ICON_SIZE_DIP + WidgetItemView.ICON_MARGIN_DIP + WidgetItemView.MARGIN_VERTICAL_DIP ); } else { this.TREND_ITEM_HEIGHT = DisplayUtils.dpToPx( getContext(), WidgetItemView.TREND_VIEW_HEIGHT_DIP_1X); this.BOTTOM_MARGIN = DisplayUtils.dpToPx( getContext(), WidgetItemView.MARGIN_VERTICAL_DIP); } invalidate(); } private void computeCoordinates() { historyTempYs = new int[] { computeSingleCoordinate(historyTemps[0], highestTemp, lowestTemp), computeSingleCoordinate(historyTemps[1], highestTemp, lowestTemp) }; } private int computeSingleCoordinate(float value, float max, float min) { float canvasHeight = TREND_ITEM_HEIGHT - TREND_MARGIN_TOP - TREND_MARGIN_BOTTOM; return (int) ( getMeasuredHeight() - BOTTOM_MARGIN - TREND_MARGIN_BOTTOM - canvasHeight * (value - min) / (max - min) ); } }