2015-05-11 9 views
7

Używam klasy MarkerView do wyświetlania widoków znaczników na wykresie. Utworzony układ widoków znaczników zawiera dwa widoki tekstowe, jeden pod drugim.MarkerView wychodzi z wykresu dla ostatniego punktu na wykresie

Problem, przed którym stoję, polega na tym, że widok znacznika dla ostatniego punktu na wykresie znajduje się w połowie na wykresie, a połowa poza wykresem. Dwa obrazy poniżej stanu Problem jasno:

Pierwszy obraz przedstawia markerview do punktu w środku wykresu, który pokazuje bez problemu:

enter image description here

Drugi obraz, jak pokazano poniżej , pokazuje widok znacznika dla ostatniego punktu wykresu, który znajduje się w połowie zakresu wykresu.

enter image description here

Jak mogę dostać ten markerview aby ustawić tak, że pokazuje się w obszarze wykresu.

Wiki nie podaje żadnych dostosowań dla znacznika. Czy są jakieś dodatkowe dostosowania?

Również w przypadku wykresu wielowierszowego, jeśli kliknę tylko jeden z punktów linii, widok znacznika pojawia się bez problemu. Ale jeśli kliknę znacznik w dowolnym punkcie na drugiej linii, aplikacja nie powiedzie się. Każdy pomysł, dlaczego tak się dzieje.

Kod dla klasy markerview podano poniżej:

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

Odpowiedz

2

Wystarczy umieścić pewną logikę w MarkerView. Jeśli ostatnia wartość jest podświetlona, ​​metoda getXOffset() powinna zwrócić coś innego.

To, co jest zwracane, jest obliczane według metody refreshContent(...).

Ponadto, można również zapoznać się z następującymi właściwościami XML:

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

która powinna zostać ustalona dla Chart-view.

+0

Dwie właściwości XML nie pomagają. –

+0

Po kliknięciu punktu na wykresie pojawiają się dwie linie przecinające się w punkcie kliknięcia. Proszę odnieść się do obrazów w pytaniu. Jak usunąć te linie? –

+0

Są one nazywane liniami wskaźnika podkreślenia, zapoznaj się z [dokumentacją] (https://github.com/PhilJay/MPAndroidChart/wiki/Interaction-with-the-Chart). –

4

Od

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

nie działa dla mnie, skończyło się na 3 różne tworzenia kanału alfa. W zależności od indeksu pozycji używam jednego lub drugiego. Aby utrzymać strzałkę wyśrodkowaną, XOffset zmienia się odpowiednio. Myślę, że to bardzo specyficzne rozwiązanie, ale idea jest eksportowane

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

Jest to wynik

enter image description here enter image description here enter image description here

The kanału alfa są kopiowane z próbek MPAndroidChart, przekształca się 9.patch i dostosowane do moich potrzeb.Umieścić je wewnątrz rozciągliwej-nodpi

enter image description here enter image description here enter image description here

+0

Co to jest 9.patch? –

+0

Skorzystaj z Goole ... http://developer.android.com/tools/help/draw9patch.html – Maragues

+0

Istnieją narzędzia do tworzenia 9 obrazów łatek. Ale jak działają? Jak przekonwertować zwykły obraz na 9 łatek? –

5

Trochę późno, ale tutaj jest moje proste rozwiązanie tego problemu.

Musisz Override z metody draw swojego niestandardowego MarkerView.

Po prostu musisz kontrolować, że posx nie zamyka się z jednego z twoich obramowań (z 0 dla prawej strony do lokalizacji w zależności od rozmiaru ekranu, na przykład na mój własny ekran na przykład 300).

Prosty przykład:

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

Tutaj mogę kontrolować pozycję x podczas upewniając się, że znacznik pozostanie zawsze w górnej części wykresu (Jeśli nie chcesz, stosowanie p osy += getYOffset(); zamiast)

+0

Dzięki temu pomaga. – rolyanos

2

Zmierzyłem się z tym samym problemem. I to naprawione poprzez mój własny customMarkerview klasa szczególnie poniższy sposób:

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

znalazłem proste rozwiązanie tego problemu. Trzeba ustawić wykres w niestandardowym markera widzenia, jak poniżej:

setChartView(chart); 

..i zastąpić metodę draw jak poniżej:

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

Najlepszą odpowiedź leży w samej bibliotece. Sprawdź metodę getOffsetForDrawingAtPoint() od MarkerView. Zdefiniował idealny sposób obliczania przesunięcia. Użyj tej logiki stamtąd i użyj w metodzie onDraw niestandardowego znacznika jako:

@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); 
    } 
+0

Nie trzeba przesłonić losowania, jeśli wywołasz setChartView (wykres), wtedy getOffsetForDrawingAtPoint() obliczy poprawnie przesunięcie –