我有一个BarChart,在点击指标时会填充它。此外,此BarChart具有自定义标记,我不了解原因,但有时可行,有时不可行。 (Check the video)。似乎图表未正确失效。
包含图表(XML)的片段代码。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="@dimen/workout_summary_expand_collapse_container_padding_bottom"
android:clipChildren="false"
android:clipToPadding="false">
<com.github.mikephil.charting.charts.BarChart
android:id="@+id/workout_summary_premium_metrics_detail_bar_chart"
android:layout_width="match_parent"
android:layout_height="@dimen/workout_detail_bar_chart_height"
android:layout_marginTop="10dp"
android:background="@drawable/background_detail_sub_section_card"
android:layout_marginStart="@dimen/workout_summary_premium_margin"
android:layout_marginEnd="@dimen/workout_summary_premium_margin"
android:clipChildren="false"
android:clipToPadding="false"
android:visibility="gone"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/workout_summary_premium_metrics_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp" />
</LinearLayout>
包含图表的片段代码。
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setUpChart();
}
private void setUpChart() {
int colorGray = ContextCompat.getColor(getActivity(), R.color.gray_chart_dash);
Typeface typeface = FontUtil.getTypeface(getContext(), FontUtil.CHART_FONT);
barChart.getLegend().setEnabled(false);
Description description = new Description();
description.setText("");
barChart.setDescription(description);
barChart.getAxisRight().setEnabled(false);
barChart.getAxisLeft().setTypeface(typeface);
barChart.getAxisLeft().setTextColor(colorGray);
barChart.getAxisLeft().setGridColor(colorGray);
barChart.getAxisLeft().setAxisLineColor(Color.TRANSPARENT);
barChart.getXAxis().setAxisLineColor(Color.TRANSPARENT);
barChart.getXAxis().setGridColor(ContextCompat.getColor(getActivity(), R.color.gray_chart_dash));
barChart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM);
barChart.getXAxis().setTypeface(typeface);
barChart.getXAxis().setTextColor(colorGray);
barChart.getXAxis().setGranularity(1f);
barChart.setNoDataTextColor(ContextCompat.getColor(getContext(), R.color.defaultTextColor));
barChart.setNoDataTextTypeface(typeface);
barChart.setExtraOffsets(0f, 35f, 0, 10f);
//setup custom marker
barChart.setMarker(new CustomChartMarkerView(getContext(), R.layout.custom_chart_marker_view,
R.drawable.background_meditation_chart_text, R.color.defaultBackgroundAlpha, barChart, true, true, false));
barChart.setHighlightPerTapEnabled(true);
barChart.setHighlightPerDragEnabled(true);
barChart.setTouchEnabled(true);
barChart.setPinchZoom(false);
barChart.setScaleEnabled(false);
barChart.setDoubleTapToZoomEnabled(false);
barChart.setDrawMarkers(true);
}
@Override
public void onWorkoutSummaryItemSelected(@NonNull WorkoutSummaryItem item) {
resetChart();
BarData barData = new BarData();
barData.setBarWidth(Constants.BAR_SMALL_WIDTH);
if (!item.entries.isEmpty()) {
BarDataSet dataSet = new BarDataSet(item.entries, null);
dataSet.setColor(ContextCompat.getColor(getContext(), R.color.workout_summary_item_selected));
dataSet.setDrawValues(false);
dataSet.setDrawIcons(false);
dataSet.setHighLightColor(ContextCompat.getColor(getContext(), R.color.defaultTextColor));
dataSet.setHighLightAlpha(255);
dataSet.setHighlightEnabled(true);
barChart.getXAxis().setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
SimpleDateFormat dateFormat;
DateTime date;
if (granularity == GetWorkoutSummaryRequest.SummaryGranularity.Year) {
dateFormat = DATE_FORMAT_X_AXIS_MONTH;
date = TimeUtils.fromMonthsBetweenEpoch((int) value);
} else {
dateFormat = DATE_FORMAT_X_AXIS_DAY;
date = TimeUtils.fromDaysBetweenEpoch((int) value);
}
return dateFormat.format(date.toDate());
}
});
barChart.getAxisLeft().setAxisMaximum(dataSet.getYMax() + 5);
((CustomChartMarkerView) barChart.getMarker()).setBottomUnit(item.unit);
barData.addDataSet(dataSet);
}
barChart.setData(barData);
barChart.animateXY(0, Constants.ANIMATION_DURATION);
barChart.invalidate();
}
private void resetChart() {
barChart.highlightValue(null);
barChart.clear();
barChart.fitScreen();
if (barChart.getData() != null) {
barChart.getData().clearValues();
}
barChart.getXAxis().setValueFormatter(null);
barChart.notifyDataSetChanged();
barChart.invalidate();
}
CustomMarker代码。
public class CustomChartMarkerView extends MarkerView {
public static final String MARKER_TYPE_TIMESTAMP = "timestamp";
public static final String MARKER_TYPE_MINUTES = "minutes";
public static final String MARKER_TYPE_SECONDS = "seconds";
public static final String MARKER_TYPE_HOURS = "hours";
public static final String MARKER_TYPE_WEEK_MONTH_YEAR = "week_month_year";
public static final String MARKER_TYPE_MINUTES_FROM_EPOCH = "minutes_from_epoch";
private CustomTextView topLabel;
private CustomTextView bottomLabel;
private String topUnit;
private String bottomUnit;
private boolean useAxisXFormatter = false;
private boolean useAxisYFormatter = false;
private boolean hasBringToFront = false;
private long extraTimestampOffset = 0; //Hack for meditations activity charts
private String extraTopUnitTextInfo = ""; //Hack workout details charts
private String extraBottomUnitTextInfo = ""; //Hack workout details charts
private final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("hh:mm a", Locale.getDefault());
private final SimpleDateFormat DATE_FORMAT_WEEK_MONTH_YEAR = new SimpleDateFormat("MMM d", Locale.getDefault());
public CustomChartMarkerView(Context context, @LayoutRes int layoutResource,
@DrawableRes int backgroundRes, @ColorRes int textColor,
String topUnit, String bottomUnit, Chart chart, boolean useAxisXFormatter,
boolean useAxisYFormatter, boolean hasBringToFront) {
super(context, layoutResource);
this.useAxisXFormatter = useAxisXFormatter;
this.useAxisYFormatter = useAxisYFormatter;
this.hasBringToFront = hasBringToFront;
this.topUnit = topUnit;
this.bottomUnit = bottomUnit;
setChartView(chart);
setBackgroundResource(backgroundRes);
topLabel = findViewById(R.id.chart_marker_view_top_label);
bottomLabel = findViewById(R.id.chart_marker_view_bottom_label);
topLabel.setTextColor(ContextCompat.getColor(context, textColor));
bottomLabel.setTextColor(ContextCompat.getColor(context, textColor));
}
public CustomChartMarkerView(Context context, @LayoutRes int layoutResource,
@DrawableRes int backgroundRes, @ColorRes int textColor,
String topUnit, String bottomUnit, Chart chart) {
this(context, layoutResource, backgroundRes, textColor, topUnit, bottomUnit, chart, false, false, false);
}
public CustomChartMarkerView(Context context, @LayoutRes int layoutResource,
@DrawableRes int backgroundRes, @ColorRes int textColor, Chart chart, boolean useAxisXFormatter,
boolean useAxisYFormatter, boolean hasBringToFront) {
this(context, layoutResource, backgroundRes, textColor, "", "", chart, useAxisXFormatter, useAxisYFormatter, hasBringToFront);
}
@Override
public void refreshContent(Entry e, Highlight highlight) {
switch (topUnit.toLowerCase()) {
case MARKER_TYPE_WEEK_MONTH_YEAR:
topLabel.setText(getFinalTextLeftUnit(DATE_FORMAT_WEEK_MONTH_YEAR.format(TimeUtils.fromDaysBetweenEpoch((int) e.getX()).toDate())));
break;
case MARKER_TYPE_TIMESTAMP:
topLabel.setText(getFinalTextLeftUnit(DATE_FORMAT.format(new DateTime((int) e.getX() + extraTimestampOffset).toDate())));
break;
case MARKER_TYPE_MINUTES:
topLabel.setText(getFinalTextLeftUnit(TimeUtils.formatSeconds((int) (e.getX() * 60))));
break;
case MARKER_TYPE_SECONDS:
topLabel.setText(getFinalTextLeftUnit(TimeUtils.formatSeconds((int) (e.getX()))));
break;
case MARKER_TYPE_HOURS:
topLabel.setText(getFinalTextLeftUnit(TimeUtils.formatSeconds((int) (e.getX() * 60 * 60))));
break;
case MARKER_TYPE_MINUTES_FROM_EPOCH:
topLabel.setText(getFinalTextLeftUnit(DATE_FORMAT.format(TimeUtils.fromMinutesBetweenEpoch((int) e.getX()).toDate())));
break;
default:
if (useAxisXFormatter && getChartView().getXAxis().getValueFormatter() != null) {
String label = getChartView().getXAxis().getValueFormatter().getFormattedValue(e.getX(), getChartView().getXAxis()).replaceAll("\n", " ");
topLabel.setText(getFinalTextLeftUnit(label));
} else {
topLabel.setText(getFinalTextLeftUnit(Constants.DECIMAL_FORMAT_1.format(e.getX())));
}
break;
}
switch (bottomUnit.toLowerCase()) {
case MARKER_TYPE_WEEK_MONTH_YEAR:
bottomLabel.setText(getFinalTextRightUnit(DATE_FORMAT_WEEK_MONTH_YEAR.format(TimeUtils.fromDaysBetweenEpoch((int) e.getY()).toDate())));
break;
case MARKER_TYPE_TIMESTAMP:
bottomLabel.setText(getFinalTextRightUnit(DATE_FORMAT.format(new DateTime((int) e.getY() + extraTimestampOffset).toDate())));
break;
case MARKER_TYPE_MINUTES:
bottomLabel.setText(getFinalTextRightUnit(TimeUtils.formatSeconds((int) (e.getY() * 60))));
break;
case MARKER_TYPE_SECONDS:
bottomLabel.setText(getFinalTextRightUnit(TimeUtils.formatSeconds((int) (e.getY()))));
break;
case MARKER_TYPE_HOURS:
bottomLabel.setText(getFinalTextRightUnit(TimeUtils.formatSeconds((int) (e.getY() * 60 * 60))));
break;
case MARKER_TYPE_MINUTES_FROM_EPOCH:
bottomLabel.setText(getFinalTextRightUnit(DATE_FORMAT.format(TimeUtils.fromMinutesBetweenEpoch((int) e.getY()).toDate())));
default:
if (useAxisYFormatter) {
if (getChartView() instanceof BarChart && ((BarChart) getChartView()).getAxisLeft().getValueFormatter() != null) {
AxisBase axis = ((BarChart) getChartView()).getAxisLeft();
String label = axis.getValueFormatter().getFormattedValue(e.getY(), axis);
bottomLabel.setText(getFinalTextRightUnit(label));
} else {
bottomLabel.setText(getFinalTextRightUnit(Constants.DECIMAL_FORMAT_1.format(e.getY())));
}
} else {
bottomLabel.setText(getFinalTextRightUnit(Constants.DECIMAL_FORMAT_1.format(e.getY())));
}
break;
}
super.refreshContent(e, highlight);
/*if (getChartView() instanceof BarChart) {
setOffset(-getWidth() / 2, -getHeight() + getContext().getResources().getDimensionPixelSize(R.dimen.extra_offset_y_marker_bar));
} else {
setOffset(-getWidth() / 2, -highlight.getYPx());
}*/
setOffset(-getWidth() / 2, -highlight.getYPx());
if (hasBringToFront) {
getChartView().bringToFront();
}
}
private String getFinalTextLeftUnit(String text) {
StringBuilder builder = new StringBuilder(text.trim());
if (StringUtils.isNotBlank(topUnit) && !isCustomMarkerUnit(topUnit.toLowerCase())) {
builder.append(" ").append(topUnit.toUpperCase());
}
if (StringUtils.isNotBlank(getExtraTopUnitTextInfo())) {
builder.append(" ").append(getExtraTopUnitTextInfo());
}
return builder.toString();
}
private boolean isCustomMarkerUnit(String unit) {
return MARKER_TYPE_TIMESTAMP.equals(unit) ||
MARKER_TYPE_MINUTES.equals(unit) ||
MARKER_TYPE_SECONDS.equals(unit) ||
MARKER_TYPE_HOURS.equals(unit) ||
MARKER_TYPE_WEEK_MONTH_YEAR.equals(unit) ||
MARKER_TYPE_MINUTES_FROM_EPOCH.equals(unit);
}
private String getFinalTextRightUnit(String text) {
StringBuilder builder = new StringBuilder(text.trim());
if (StringUtils.isNotBlank(bottomUnit) && !isCustomMarkerUnit(bottomUnit.toLowerCase())) {
builder.append(" ").append(bottomUnit.toUpperCase());
}
if (StringUtils.isNotBlank(getExtraBottomUnitTextInfo())) {
builder.append(" ").append(getExtraBottomUnitTextInfo());
}
return builder.toString();
}
@Override
public void draw(Canvas canvas, float posX, float posY) {
super.draw(canvas, posX, posY);
getOffsetForDrawingAtPoint(posX, posY);
}
}
谢谢。