MarkerView выходит из графика для последней точки на графике

Я использую класс MarkerView для отображения маркеров в диаграмме. Макет markerview, который я создал, содержит два текстовых поля, один под другим.

Проблема, с которой я сталкиваюсь, заключается в том, что маркер для последней точки на графике находится в пределах половины графика и половину диаграммы. На двух изображениях ниже четко указывается проблема:

На первом изображении отображается маркер для точки в центре диаграммы, которая показывает без проблем:

Введите описание изображения здесь

Второе изображение, как показано ниже, показывает маркер для последней точки диаграммы, которая находится в половине диаграммы.

Введите описание изображения здесь

Как мне настроить этот маркер, чтобы он отображался в области диаграммы.

В вики не указано никаких настроек для 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(); } } 

Просто MarkerView логику в свой MarkerView . Если последнее значение выделено, метод getXOffset() должен возвращать что-то другое.

Возвращаемое значение вычисляется refreshContent(...) .

Кроме того, вы можете взглянуть на следующие свойства xml:

 android:clipChildren="false" android:clipToPadding="false" 

Который должен быть установлен для просмотра диаграммы.

Немного поздно, но вот мое легкое решение этой проблемы.

Вам необходимо 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(); вместо этого)

поскольку

 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); } 

Это результат

Введите описание изображения здесьВведите описание изображения здесьВведите описание изображения здесь

Выделенные копии копируются из образцов MPAndroidChart, преобразованных в 9.patch и адаптированных к моим потребностям. Поместите их внутрь drawable-nodpi

Введите описание изображения здесьВведите описание изображения здесьВведите описание изображения здесь

Я столкнулся с той же проблемой. Я исправил его, создав собственный собственный 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); } 

Я нашел простое решение этой проблемы. Вам необходимо установить диаграмму в своем пользовательском виде маркера, как показано ниже:

 setChartView(chart); 

.. и переопределить метод рисования, как показано ниже:

 @Override public void draw(Canvas canvas, float posX, float posY) { super.draw(canvas, posX, posY); getOffsetForDrawingAtPoint(posX, posY); } 

Лучший ответ лежит в самой библиотеке. Проверьте метод 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); }