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 hereenter image description hereenter image description here

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

enter image description hereenter image description hereenter 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);
    }