MarkerView выходит из графика для последней точки на графике
Я использую класс MarkerView для отображения маркеров в диаграмме. Макет markerview, который я создал, содержит два текстовых поля, один под другим.
Проблема, с которой я сталкиваюсь, заключается в том, что маркер для последней точки на диаграмме находится наполовину внутри диаграммы и наполовину вне графика. Два изображения ниже четко указывают проблему:
Первое изображение показывает маркер для точки в центре диаграммы, которая показывает без проблем:
![enter image description here]()
Второе изображение, как показано ниже, показывает markerview для последней точки диаграммы, которая находится в половине диаграммы.
![enter image description here]()
Как мне настроить этот маркер, чтобы он отображался в области диаграммы.
В вики не указано никаких настроек для markerview. Есть ли еще какие-то настройки?
Кроме того, в случае многострочной диаграммы, если я нажимаю только на одну из точек линии, markerview возникает без проблем. Но если я нажму на markerview в любой точке другой строки, приложение завершится неудачно. Любая идея, почему это происходит.
Код класса markerview приведен ниже:
public class TooltipView extends MarkerView {
private BaseGraphMetadata mBaseGraphMetadata;
private TextView mTooltipDate, mTooltipValue;
public TooltipView(Context context, int layoutResource, BaseGraphMetadata baseGraphMetadata) {
super(context, layoutResource);
mTooltipDate = (TextView)findViewById(R.id.tooltip_date);
mTooltipValue = (TextView)findViewById(R.id.tooltip_value);
mBaseGraphMetadata = baseGraphMetadata;
}
@Override
public void refreshContent(Entry entry, int i) {
List<DrillDownInfo> drillDownInfoList = (List<DrillDownInfo>) entry.getData();
DrillDownInfo drillDownInfo = drillDownInfoList.get(i);
Map<String, String> group = drillDownInfo.getGroupByNameVsGroupByValue();
Iterator iterator = group.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry pair = (Map.Entry)iterator.next();
if(pair.getKey()!=null && pair.getValue()!=null) {
String key = (String) pair.getKey();
key = key.toUpperCase();
Double value = Double.parseDouble((String) pair.getValue());
String formattedValue = mBaseGraphMetadata.getDataFormatter().getFormattedValue(value);
mTooltipDate.setText(key + " : " + formattedValue);
}
iterator.remove();
}
mTooltipValue.setText(String.valueOf("VALUE : "+entry.getVal()));
}
@Override
public int getXOffset() {
return -(getWidth() / 2);
}
@Override
public int getYOffset() {
return -getHeight();
}
}
Ответы
Ответ 1
Просто MarkerView
немного логики в свой MarkerView
. Если последнее значение выделено, метод getXOffset()
должен вернуть что-то другое.
То, что возвращается, вычисляется в refreshContent(...)
.
Также вы можете взглянуть на следующие свойства xml:
android:clipChildren="false"
android:clipToPadding="false"
Который должен быть установлен для просмотра графика.
Ответ 2
С
android:clipChildren="false"
android:clipToPadding="false"
не работал у меня, я создал 3 разных чертежа. В зависимости от индекса ввода я использую тот или иной. И, чтобы сохранить стрелку в центре, изменяется XOffset. Я предполагаю, что это очень специфическое решение, но идея экспортируется
@Override
public void refreshContent(Entry e, int dataSetIndex) {
if (e.getXIndex() < 4) {
xOffsetMultiplier = 3.2f;
tvContent.setBackgroundResource(R.drawable.stats_marker_left_side);
} else if (e.getXIndex() > mTimestamps.length - 6) {
//timestamps is an array containing xValues timestamps
xOffsetMultiplier = 1.12f;
tvContent.setBackgroundResource(R.drawable.stats_marker_right_side);
} else {
xOffsetMultiplier = 2;
tvContent.setBackgroundResource(R.drawable.stats_marker);
}
tvContent.setText(createMarkerViewText(e));
}
@Override
public int getXOffset() {
// this will center the marker-view horizontally
return (int) -(getWidth() / xOffsetMultiplier);
}
Это результат
![enter image description here]()
![enter image description here]()
![enter image description here]()
Выделимые копии копируются из образцов MPAndroidChart, преобразованных в 9.patch и адаптированных к моим потребностям. Поместите их внутрь drawable-nodpi
![enter image description here]()
![enter image description here]()
![enter image description here]()
Ответ 3
Я нашел простое решение этой проблемы. Вам необходимо установить диаграмму в своем пользовательском виде маркера, как показано ниже:
setChartView(chart);
.. и переопределить метод рисования, как показано ниже:
@Override
public void draw(Canvas canvas, float posX, float posY) {
super.draw(canvas, posX, posY);
getOffsetForDrawingAtPoint(posX, posY);
}
Ответ 4
Немного поздно, но вот мое легкое решение этой проблемы.
Вам нужно Override
метод draw
вашего пользовательского MarkerView
.
Вы просто должны контролировать, что вы не станете закрываться с одной из ваших границ (от 0
для правой стороны к местоположению в зависимости от размера экрана, как пример 300
для моего собственного экрана).
Простой пример:
@Override
public void draw(Canvas canvas, float posx, float posy)
{
// take offsets into consideration
posx += getXOffset();
posy=0;
// AVOID OFFSCREEN
if(posx<45)
posx=45;
if(posx>265)
posx=265;
// translate to the correct position and draw
canvas.translate(posx, posy);
draw(canvas);
canvas.translate(-posx, -posy);
}
Здесь я могу контролировать свою позицию x, пока гарантирует, что маркер останется всегда в верхней части графика (если вы этого не хотите, вместо этого используйте p osy += getYOffset();
)
Ответ 5
Я столкнулся с той же проблемой. Я исправил его, создав свой собственный класс customMarkerview
, в частности, ниже:
@Override
public int getXOffset(float xpos) {
// this will center the marker-view horizontally
int min_offset = 50;
if (xpos < min_offset)
return 0;
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metrics);
//For right hand side
if (metrics.widthPixels - xpos < min_offset)
return -getWidth();
//For left hand side
else if (metrics.widthPixels - xpos < 0)
return -getWidth();
return -(getWidth() / 2);
}
Ответ 6
Лучший ответ лежит в самой библиотеке. Проверьте метод getOffsetForDrawingAtPoint() из MarkerView. Он определил идеальный способ вычисления смещения. Используйте эту логику оттуда и используйте в onDraw
метод вашего настраиваемого маркера следующим образом:
@Override
public void draw(Canvas canvas, float posX, float posY) {
// take offsets into consideration
int lineChartWidth = 0;
float offsetX = getOffset().getX();
posY=0;//fix at top
float width = getWidth();
if(lineChart != null) {
lineChartWidth = lineChart.getWidth();
}
if(posX + offsetX < 0) {
offsetX = - posX;
} else if(posX + width + offsetX > lineChartWidth) {
offsetX = lineChartWidth - posX - width;
}
posX += offsetX;
// translate to the correct position and draw
canvas.translate(posX, posY);
draw(canvas);
canvas.translate(-posX, -posY);
}