سؤال

The wheel View (CircleView) is working fine in major of devices but this error coming from S4 and Note 3 devices.

The touch is getting deducted but the that not fall under the weidgetregion.

false - 1 has to be true - 1

Region Log is:

enter image description here

My Circle View code is

 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;
}
}
هل كانت مفيدة؟

المحلول 2

At last i found my mistake in this code that it is working in mdpi and htpi and not in xxhdpi the reason is

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

The bound exceeds the circle size, i mean the xxhdpi draws an circle with 1000x1000 values, so i made this too like this (max values)

mWedgeRegion.setPath( this, new Region(0,0,720,1200) )

نصائح أخرى

First of all, look at line 307. Learn how to read crash logs because it says exactly on what line the crash is, and then it shouldn't be too hard too determine what is wrong.

Not knowing what line it is I guess that mWedges might be null. in the onTouch you do for(Wedge day : mWedges) but it is not guaranteed that is isn't null there. You should check before you do that if it is null.

You put it to a non null value in determineWedges but only when there is at least 1 mMenuEntries. So when there are no entries when you do an onTouch it will crash.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top