MPAndroidChart - 在MarkerView中单击按钮

时间:2016-06-22 05:21:24

标签: android mpandroidchart

目前我在布局中有一个Button,但是指定的OnClickListener从不回调onClick方法。

是否可以拦截分配给MarkerView的布局中的按钮单击?

2 个答案:

答案 0 :(得分:1)

使用该库似乎不可能,但是各种解决方案是在图表上显示View或ViewGroup,其中包含一个Button。您需要为MarkerView设置一个空布局,并将您的图表包装在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();
}

希望这有帮助。

答案 1 :(得分:1)

我已经使用可点击的标记视图完成了我的应用。我的解决方案是我们将创建LineChart(或其他图表)的子类,然后重写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;
    }
}