android:canvas触摸不在s4中工作

问题描述 投票:0回答:2

帮我解决这个问题。轮视图(CircleView)在主要设备中运行良好,但此错误来自s4和note 3设备。

触摸被扣除,但不属于weidgetregion。

假 - 1必须是真的 - 1

区域日志是我的圈子视图代码是

 public class CircleView extends View implements OnTouchListener{
boolean firstTime = false;
private List<CircleViewBean> mMenuEntries = new ArrayList<CircleViewBean>();
private OnCellTouchListener mOnCellTouchListener = null;
public interface OnCellTouchListener {
    public void onTouch(Wedge cell);
}
private Shader mShader;

private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);

private float screen_density = getContext().getResources().getDisplayMetrics().density;

//Radius of inner ring size
private int mMinSize = scalePX(60);
//Radius of outer ring size
private int mMaxSize = scalePX(170);
private int mWedgeQty = 6;
//Center X location of Radial Menu
private int xPosition = scalePX(120);
//Center Y location of Radial Menu
private int yPosition = scalePX(120);
int touchIndex = -1;
private Wedge[] mWedges;

private RectF mViewRect = new RectF();

private int scalePX( int dp_size )
{
    return (int) (dp_size * screen_density + 0.5f);
}

public CircleView(Context context) {
    this(context, null);
}

public CircleView(Context context, AttributeSet attrs) {
    super(context, attrs);
    HashMap<String, String> device = Constants.getDeviceDetails(getResources().getDisplayMetrics().heightPixels, getResources().getDisplayMetrics().widthPixels);
    mMinSize = Integer.parseInt(device.get("in_arc"));
    mMaxSize = Integer.parseInt(device.get("out_arc"));
    setBackgroundResource(R.drawable.centre_wheel);
}
private void determineWedges() {
    int entriesQty = mMenuEntries.size();
    if ( entriesQty > 0) {
        mWedgeQty = entriesQty;

        float degSlice = 360 / mWedgeQty;
        float start_degSlice = 270 - (degSlice/2);
        //calculates where to put the images

        this.mWedges = new Wedge[mWedgeQty];

        double mid = 0, min = 0, max = 0;
        for(int i = 0; i < this.mWedges.length; i++) {
            this.mWedges[i] = new Wedge(xPosition, yPosition, mMinSize, mMaxSize, (i
                    * degSlice)+start_degSlice, degSlice, mMenuEntries.get(i).getIndex());

            mid = this.mWedges[i].midValue = normalizeAngle( ((i * degSlice) + start_degSlice + degSlice) / 2 );
            min = normalizeAngle( (i * degSlice) + start_degSlice );
            max = normalizeAngle( (i * degSlice) + start_degSlice + degSlice);

            this.mWedges[i].minValue = min;
            this.mWedges[i].midValue = mid;
            this.mWedges[i].maxValue = max;

            mViewRect.union( new RectF( mWedges[i].getWedgeRegion().getBounds() ) );
        }

        mShader = new RadialGradient(xPosition, yPosition, mMaxSize, new int[] { 0xff595756, 0xffCCC5C3, 0xf878280}, null, Shader.TileMode.MIRROR);
        invalidate();
    }
} 

@Override
public void onDraw(Canvas canvas) {
    if(!firstTime){
        firstTime = true;
        this.xPosition = (int) (getWidth()/2f);
        this.yPosition = (int) (getHeight()/2f);
        determineWedges();
    }
    canvas.scale(getWidth() / mViewRect.width(), getHeight() / mViewRect.width(), xPosition, yPosition);
    //Saving the canvas and later restoring it so only this image will be rotated.
    canvas.save(Canvas.MATRIX_SAVE_FLAG);

    canvas.restore();
    canvas.save();
    canvas.restore();

    mPaint.setShader( mShader );  
}

private double normalizeAngle(double angle) {
    if(angle >= 0) {
        while( angle > 360 ) {
            angle -= 360;
        }
    }
    else {
        while( angle < -360) {
            angle += 360;
        }
    }
    return angle;
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // TODO Auto-generated method stub
    int wmode = MeasureSpec.getMode(widthMeasureSpec);
    int hmode = MeasureSpec.getMode(heightMeasureSpec);
    int wsize = MeasureSpec.getSize(widthMeasureSpec);
    int hsize = MeasureSpec.getSize(heightMeasureSpec);

    int width = (int)mViewRect.width();
    int height = (int) mViewRect.height();

    if (wmode == MeasureSpec.EXACTLY) {
        width = wsize;
    }
    if (hmode == MeasureSpec.EXACTLY) {
        height = hsize;
    }
    this.setMeasuredDimension(width, height);
    invalidate();

}

public class Wedge extends Path {
    private int x, y;
    private int InnerSize, OuterSize;
    private float StartArc;
    private float ArcWidth;
    private Region mWedgeRegion;
    private int index=0;
    public double minValue;
    public double midValue;
    public double maxValue;
    private Wedge(int x, int y, int InnerSize, int OuterSize, float StartArc, float ArcWidth, int category) {
        super();
        this.index = category;
        if (StartArc >= 360) {
            StartArc = StartArc-360;
        }

        minValue = midValue = maxValue = 0;
        mWedgeRegion = new Region();
        this.x = x; this.y = y;
        this.InnerSize = InnerSize;
        this.OuterSize = OuterSize;
        this.StartArc = StartArc;
        this.ArcWidth = ArcWidth;
        this.buildPath();
    }
    public int getCategoryIndex(){
        return this.index;
    }
    public String toString() {
        return minValue + "  " + midValue + "  " + maxValue;
    }
    /**
     * 
     * @return the bottom rect that will be used for intersection 
     */
    public Region getWedgeRegion() {
        return mWedgeRegion;
    }

    private void buildPath() {

        final RectF rect = new RectF();
        final RectF rect2 = new RectF();

        //Rectangles values
        rect.set(this.x-this.InnerSize, this.y-this.InnerSize, this.x+this.InnerSize, this.y+this.InnerSize);
        rect2.set(this.x-this.OuterSize, this.y-this.OuterSize, this.x+this.OuterSize, this.y+this.OuterSize);

        this.reset();
        //this.moveTo(100, 100);
        this.arcTo(rect2, StartArc, ArcWidth);
        this.arcTo(rect, StartArc+ArcWidth, -ArcWidth);

        this.close();

        mWedgeRegion.setPath( this, new Region(0,0,480,800) );
    }
}

public boolean addMenuEntry(CircleViewBean menuEntry) {
    mMenuEntries.add(menuEntry);
    return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
    if(event.getAction() == MotionEvent.ACTION_UP){
        if(mOnCellTouchListener!=null && touchIndex >-1){
            int i=0;
            for(Wedge day : mWedges) {
                if(day.getWedgeRegion().getBounds().contains((int)event.getX(), (int)event.getY()) && touchIndex==i) {
                    mOnCellTouchListener.onTouch(mWedges[touchIndex]);
                    break;
                }
                i++;
            }
        }
    }else if(event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE){
        int i=0;
        for(Wedge day : mWedges) {
            if(day.getWedgeRegion().getBounds().contains((int)event.getX(), (int)event.getY())) {
                touchIndex = i;
                setBackgroundResource(mMenuEntries.get(touchIndex).getIcon());
            }
            i++;
        }
    }
    return true;
}
public void setOnCellTouchListener(OnCellTouchListener p) {
    mOnCellTouchListener = p;
}

public boolean onTouch(View v, MotionEvent event) {
    return false;
}

}

android error-handling nullpointerexception android-canvas android-wheel
2个回答
1
投票

首先,看看第307行。了解如何阅读崩溃日志,因为它确切地说明崩溃是在什么线上,然后它也不应该太难确定什么是错误的。

不知道它是什么线,我猜mWedges可能是null。在onTouch中你做for(Wedge day : mWedges)但不保证那里不是null。如果它为空,您应该在执行此操作之前进行检查。

你把它放在determineWedges中的非空值,但只有当至少有1个mMenuEntries时。因此,当你执行onTouch时没有条目时它会崩溃。


0
投票

最后我发现我在这段代码中的错误是它在mdpi和htpi中工作而不是在xxhdpi中,原因是

mWedgeRegion.setPath( this, new Region(0,0,480,800) );

绑定超过圆的大小,我的意思是xxhdpi绘制一个1000x1000值的圆,所以我也这样做(最大值)

mWedgeRegion.setPath( this, new Region(0,0,720,1200) )
© www.soinside.com 2019 - 2024. All rights reserved.