2016-06-22 107 views

回答

1

使用庫似乎不可能,但是排序的解決方案是在圖表上顯示一個View或ViewGroup,該圖表中有一個Button。您需要爲MarkerView設置一個空的佈局,並將您的Chart包裹在ViewGroup中,例如RelativeLayout。

定義監聽像這樣在你的CustomMarkerView:

public interface Listener { 
    /** 
    * A callback with the x,y position of the marker 
    * @param x the x in pixels 
    * @param y the y in pixels 
    */ 
    void onMarkerViewLayout(int x, int y); 
} 

設置一些成員變量:

private Listener mListener; 
private int mLayoutX; 
private int mLayoutY; 
private int mMarkerVisibility; 

在你的構造需要監聽器:

/** 
    * Constructor. Sets up the MarkerView with a custom layout resource. 
    * @param context a context 
    * @param layoutResource the layout resource to use for the MarkerView 
    * @param listener listens for the bid now click 
    */ 
    public SQUChartMarkerView(Context context, int layoutResource, Listener listener) { 
     super(context, layoutResource); 
     mListener = listener; 
    } 

商店標記應該在設置值時的位置:

@Override public int getXOffset(float xpos) { 
    mLayoutX = (int) (xpos - (getWidth()/2)); 
    return -getWidth()/2; 
} 


@Override public int getYOffset(float ypos) { 
    mLayoutY = (int) (ypos - getWidth()); 
    return -getHeight(); 
} 

然後重寫的onDraw確定何時應該借鑑佈局:

@Override protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 
    if(mMarkerVisibility == View.VISIBLE) mListener.onMarkerViewLayout(mLayoutX, mLayoutY); 
} 

我添加了一個選項來改變標誌的狀態:你在哪裏聽標記物是

public void setMarkerVisibility(int markerVisibility) { 
    mMarkerVisibility = markerVisibility; 
} 

佈局,得到你的佈局(例如。充氣它或者你可能把它作爲一個成員變量),確保你測量它,然後設置邊距。在這種情況下,我使用getParent()作爲圖表,標記的佈局共享相同的父級。我有一個BarChart,所以我的利潤可能與您的利潤不同。

@Override public void onMarkerViewLayout(int x, int y) { 
    if(getParent() == null || mChartListener.getAmount() == null) return; 
    // remove the marker 
    ((ViewGroup) getParent()).removeView(mMarkerLayout); 
    ((ViewGroup) getParent()).addView(mMarkerLayout); 

    // measure the layout 
    // if this is not done, the first calculation of the layout parameter margins 
    // will be incorrect as the layout at this point has no height or width 
    int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(((ViewGroup) getParent()).getWidth(), View.MeasureSpec.UNSPECIFIED); 
    int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(((ViewGroup) getParent()).getHeight(), View.MeasureSpec.UNSPECIFIED); 
    mMarkerLayout.measure(widthMeasureSpec, heightMeasureSpec); 

    // set up layout parameters so our marker is in the same position as the mpchart marker would be (based no the x and y) 
    RelativeLayout.LayoutParams lps = (RelativeLayout.LayoutParams) mMarkerLayout.getLayoutParams(); 
    lps.height = FrameLayout.LayoutParams.WRAP_CONTENT; 
    lps.width = FrameLayout.LayoutParams.WRAP_CONTENT; 
    lps.leftMargin = x - mMarkerLayout.getMeasuredWidth()/2; 
    lps.topMargin = y - mMarkerLayout.getMeasuredHeight(); 
} 

希望這會有所幫助。

+0

使用最新的庫3.0.2,我沒有看到getXOffset()或getYOffset()存在。 –

+0

如果標記正在執行onDraw(),那麼在這裏您正在監聽,而不是用戶單擊markerView時是否真的如此。我認爲有區別。 –

0

我用可點擊的標記視圖完成了我的應用程序。我的解決方案是我們將創建LineChart(或其他圖表)的子類,然後讓override onTouchEvent並檢測觸摸位置。

public class MyChart extends LineChart { 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     boolean handled = true; 
     // if there is no marker view or drawing marker is disabled 
     if (isShowingMarker() && this.getMarker() instanceof ChartInfoMarkerView){ 
      ChartInfoMarkerView markerView = (ChartInfoMarkerView) this.getMarker(); 
      Rect rect = new Rect((int)markerView.drawingPosX,(int)markerView.drawingPosY,(int)markerView.drawingPosX + markerView.getWidth(), (int)markerView.drawingPosY + markerView.getHeight()); 
      if (rect.contains((int) event.getX(),(int) event.getY())) { 
       // touch on marker -> dispatch touch event in to marker 
       markerView.dispatchTouchEvent(event); 
      }else{ 
       handled = super.onTouchEvent(event); 
      } 
     }else{ 
      handled = super.onTouchEvent(event); 
     } 
     return handled; 
    } 

    private boolean isShowingMarker(){ 
     return mMarker != null && isDrawMarkersEnabled() && valuesToHighlight(); 
    } 
} 

public class ChartInfoMarkerView extends MarkerView { 
    @BindView(R.id.markerContainerView) 
    LinearLayout markerContainerView; 

    protected float drawingPosX; 
    protected float drawingPosY; 
    private static final int MAX_CLICK_DURATION = 500; 
    private long startClickTime; 

    /** 
    * The constructor 
    * 
    * @param context 
    * @param layoutResource 
    */ 
    public ChartInfoMarkerView(Context context, int layoutResource) { 
     super(context, layoutResource); 
     ButterKnife.bind(this); 
     markerContainerView.setClickable(true); 
     markerContainerView.setOnClickListener(new OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       Log.d("MARKER","click"); 
      } 
     }); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     switch (event.getAction()) { 
      case MotionEvent.ACTION_DOWN: { 
       startClickTime = Calendar.getInstance().getTimeInMillis(); 
       break; 
      } 
      case MotionEvent.ACTION_UP: { 
       long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime; 
       if(clickDuration < MAX_CLICK_DURATION) { 
        markerContainerView.performClick(); 
       } 
      } 
     } 
     return super.onTouchEvent(event); 
    } 

    @Override 
    public void draw(Canvas canvas, float posX, float posY) { 
     super.draw(canvas, posX, posY); 
     MPPointF offset = getOffsetForDrawingAtPoint(posX, posY); 
     this.drawingPosX = posX + offset.x; 
     this.drawingPosY = posY + offset.y; 
    } 
}