I have an Activity CropActivity, that uses my own written View CropView.
CropView extends SelectorView (also selfwritten), and SelectorView extends ImageView.
When starting the CropActivity, a NoSuchMethodException is thrown.
When using the SelectorView for the CropActivity, no error is thrown, any ideas?
The Cropview class
public class CropView extends SelectorView {
public CropView(Context context) {
super(context);
initCropView();
}
private void initCropView() {
setmPaintColor(Color.WHITE);
setsMinimumSize(metrics.densityDpi);
setsTouchBuffer(metrics.densityDpi / 3);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (getmLeftTop().equals(0, 0))
resetPoints();
// draw the points on the screen; one in every corner and one in the center
canvas.drawRect(getmLeftTop().x, getmLeftTop().y, getmRightBottom().x, getmRightBottom().y,
getmPaint());
canvas.drawCircle(getmLeftTop().x, getmLeftTop().y, 40, getmPaint());
canvas.drawCircle(getmLeftTop().x, getmRightBottom().y, 40, getmPaint());
canvas.drawCircle(getmRightBottom().x, getmLeftTop().y, 40, getmPaint());
canvas.drawCircle(getmRightBottom().x, getmRightBottom().y, 40, getmPaint());
canvas.drawCircle(getmCenter().x, getmCenter().y, 10, getmPaint());
}
Selectorview snippet
public SelectorView(Context context) {
super(context);
initSelectorView();
}
public SelectorView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
initSelectorView();
}
public SelectorView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initSelectorView();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
/**
* Initializes the cropview and variables.
*/
private void initSelectorView() {
mPaint.setStyle(Style.STROKE);
mPaint.setStrokeWidth(5);
mLeftTop = new Point();
mRightBottom = new Point();
mCenter = new Point();
mScreenCenter = new Point();
mPrevious = new Point();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int eventaction = event.getAction();
switch (eventaction) {
// set the touch point
case MotionEvent.ACTION_DOWN:
mPrevious.set((int) event.getX(), (int) event.getY());
break;
oncreate from CropActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_crop);
mContext = this;
mCropView = new CropView(this);
mFile = new File(getIntent().getStringExtra("imgpath"));
mBitmaps = new ArrayList<Bitmap>();
mTasks = new ArrayList();
mNumberOfCores = Runtime.getRuntime().availableProcessors();
mProgressDialog = new ProgressDialog(mContext);
mProgressDialog.setTitle("Enhancing image");
mBitmapDrawable = null;
mBitmapDrawable = (BitmapDrawable) Drawable.createFromPath(mFile.getAbsolutePath());
mCropView = (CropView) findViewById(R.id.image_preview);
mCropView.setImageDrawable(mBitmapDrawable);
mCropButton = (Button) findViewById(R.id.button_crop);
Custom views inflated via XML need the following constructors:
ViewName(Context)
ViewName(Context, AttributeSet)
ViewName(Context, AttributeSet, int)
You only have the first one and I guess the exception is about the second one being missing in your CropView.
Related
I am getting the error: "Cannot resolve method 'super()'" in my code and I am not sure how to resolve this, do you have any clues?
The code is as follows:
public GeoView( double left, double top, double width )
{
super();
this.left = left;
this.top = top;
this.width = width;
this.transform = null;
this.backing_store = null;
this.sink = false;
this.last_size = new Rect(0, 0, 200, 200 );
this.do_tracking = false;
Drawable background = new Drawable() {
#Override
public void draw(Canvas canvas) {
}
#Override
public void setAlpha(int i) {
}
#Override
public void setColorFilter(ColorFilter colorFilter) {
}
#Override
public int getOpacity() {
return 0;
}
};
What is GeoView class? You extended it from another class?
If yes. Check that parent class have empty constructor, because you call it.
If it's your own class and it didn't extended from any other class. Then you don't need to call super().
View doesn't have empty constructor.
You should Have at least one of this constructor.
public GeoView(Context context) {
super(context);
}
public GeoView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public GeoView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
If you want to create view by yourself, you need first constructor. Then you have to
GeoView geoView = new GeoView(YourActivity.this);
Or you can simply add your view to layout. Then You second will be called constructor. I think you should add all of them.
<com.example.yourapp.GeoView
android:layout_height="300dp"
android:layout_width="match_parent"/>
In a project of mine, I have a custom HorizontalScrollView class that displays a line chart. It gets rid of all of the elements and then it adds a single ImageView as a child element. It works fine the first time, but if I were to change to other fragment and switch back to the fragment containing the line chart, the ImageView is not present, although the object is recreated exactly the same way as the first time. If I inspect it with the DDMS the ImageView is really not in the UI graph. Any ideas why?? I really need some help on that.
That is my code (from which I have omitted some irrelevant parts):
public class LineChartView extends HorizontalScrollView {
// Private Constants ...
// Private Fields...
public LineChartView(Context context) {
super(context);
init();
}
public LineChartView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public LineChartView(Context context, float[] lineValues) {
super(context);
mLineValues = lineValues;
init();
}
public LineChartView(Context context, AttributeSet attrs, float[] lineValues) {
super(context, attrs);
mLineValues = lineValues;
init();
}
private void init() {
// Setting densityMultiplier
DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
int pixelDensity = displayMetrics.densityDpi;
mDensityMultiplier = pixelDensity / DisplayMetrics.DENSITY_DEFAULT;
// Initalising Paints...
initChildElements();
}
private void initChildElements() {
removeAllViews();
// Adding the image view to the visual graph
mChartImage = new ImageView(getContext());
ViewGroup.LayoutParams chartLayoutParams = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
mChartImage.setLayoutParams(chartLayoutParams);
addViewInLayout(mChartImage, 0, mChartImage.getLayoutParams(), true);
}
public void setLineValuesList(float[] lineValuesList) {
if (lineValuesList == null) {
mLineValues = new float[]{};
} else {
mLineValues = lineValuesList;
}
requestLayout();
invalidate();
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mChartImage.setImageDrawable(renderLineChart(h, 1.5f)); // Calculate the bitmap with the same height
super.onSizeChanged(w, h, oldw, oldh);
}
private BitmapDrawable renderLineChart(int height, float scale) {
if (height <= 0 || mLineValues.length == 0)
return null;
// Drawing logic... (not really relevant)
return new BitmapDrawable(getContext().getResources(), resultBitmap);
}
private float calculateWidth(float distanceBetween) {
int strokeCount = mLineValues.length - 1;
return strokeCount * distanceBetween;
}
private float calculateDistanceToNextValue(float scale) {
return BASE_DISTANCE_BETWEEN_POINTS * mDensityMultiplier * scale;
}
}
This is my extended View:
public class PieMenu extends FrameLayout{
private View _view;
private ArrayList<PieItem> mItems;
private Context _context;
public PieMenu(View view, Context context) {
super(context);
_context = context;
_view = view;
setWillNotDraw(false);
// TODO Auto-generated constructor stub
}
public void addPieMenu(int x, int y){
mItems = new ArrayList<PieItem>();
Path path = new Path();
path.addCircle(9, 9, 9, Path.Direction.CW);
PieItem item = new PieItem(_view,_context,path, x,y,40);
mItems.add(item);
//FrameLayout.LayoutParams lyp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
//pieView.setLayoutParams(lyp);
//addView(pieView);
// animateIn();
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
Paint paint1 = new Paint();
paint1.setColor(Color.RED);
canvas.drawCircle(50, 50, 25, paint1);
this.draw(canvas);
//_view.draw(canvas);
}
}
This is my main activity:
public class MainActivity extends Activity {
PieMenu pieMenu;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pieMenu = new PieMenu(getWindow().getDecorView().findViewById(android.R.id.content) ,MainActivity.this);
FrameLayout fl = (FrameLayout)findViewById(R.id.flayout);
fl.addView(pieMenu);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int)event.getX();
int y = (int)event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
{
pieMenu.addPieMenu(x,y);
}
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
}
return false;
}
}
This is my main activity.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/flayout"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="#string/hello_world" />
<com.example.piemenu.PieMenu
android:id="#+id/circle_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerInParent="true" />
</FrameLayout>
When I compile this, the app crashes with this error:
07-20 21:38:45.906: E/AndroidRuntime(10088): Caused by: java.lang.NoSuchMethodException: <init> [class android.content.Context, interface android.util.AttributeSet]
Where am I going wrong?
You will need these constructors in your PieMenu class:
public PieMenu(View view, Context context) {
super(context);
// ~
}
public PieMenu(View view, Context context, AttributeSet attrs) {
super(context, attrs);
// ~
}
Edit 1
public PieMenu(View view, Context context, AttributeSet attrs, int style) {
super(context, attrs, style);
// ~
}
So basically I have some image views drawn over my canvas, but when I try to set up onclick listeners and try to handle events, it doesn't work.
public class DrawView extends View implements OnClickListener{
Paint paint = new Paint();
RectF rf = new RectF(30, 30, 80, 80);
BallView ball = new BallView(getContext());
Bitmap bmp = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.ic_launcher);
public DrawView(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas) {
ball.setOnClickListener(this);
ball.draw(canvas);
canvas.drawBitmap(bmp, 110, 10, paint);
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getContext(), "Mock", Toast.LENGTH_SHORT).show();
}
}
BallView.java
public class BallView extends ImageView {
Paint b = new Paint();
public BallView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public void onDraw(Canvas c){
b.setColor(Color.BLUE);
c.drawCircle(50, 50, 40, b);
}
}
Basically the answer is: Your view is not receiving touch events, because it's not in views hierarchy, so click callback is also not called. Actually, view should be in View hierarchy (in other words, added to some upper level view and finally, to the window) in order to participate is user interactions.
So, if You want to implement somthing covering Your view, then it should be ViewGroup or shouldn't be related to view at all and be some abstract container.
E.g. using the way below click works without any issues (but You will need second view or modify BallView to draw bmp):
DrawView:
public class DrawView extends FrameLayout implements View.OnClickListener {
BallView ball = new BallView(getContext());
public DrawView(Context context) {
this(context, null, 0);
}
public DrawView(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public DrawView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
addView(ball);
ball.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Toast.makeText(getContext(), "Mock", Toast.LENGTH_SHORT).show();
}
}
BallView class stays the same.
Layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.ruinalst.performance.tests.views.DrawView
android:id="#+id/oscillator"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" />
</RelativeLayout>
I am learning how to code with Android but I am still confused bby the way it works, I am able to create simple draws like circles and stuff but now i want to paint the circle multiple times with a delay of 2 seconds.. I would appreciatge if you experts can help me improve my code and to put the stuff in the correct place
public class ColorChanges extends Activity {
DrawCircle dc;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
drawCircleToCanvas()
}
void drawCircleToCanvas()
{
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
dc.postInvalidate();
}
};
Thread updateUI = new Thread()
{
public void run() {
dc = new DrawCircle(this); //this line does not work
dc.setBackgroundColor(Color.WHITE);
setContentView(dc);
handler.sendEmptyMessage(0);
}
};
updateUI.start();
}
}
public class DrawCircle extends View {
Paint p1 = new Paint();
Paint p2 = new Paint();
Paint p3 = new Paint();
Paint pAll[] = new Paint[3];
public DrawCircle(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public DrawCircle(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public DrawCircle(Context context) {
super(context);
p1.setStyle(Paint.Style.STROKE);
p1.setColor(Color.GREEN);
p1.setStyle(Paint.Style.FILL);
p2.setStyle(Paint.Style.STROKE);
p2.setColor(Color.BLUE);
p2.setStyle(Paint.Style.FILL);
p3.setStyle(Paint.Style.STROKE);
p3.setColor(Color.YELLOW);
p3.setStyle(Paint.Style.FILL);
pAll[1] = p1;
pAll[2] = p2;
pAll[3] = p3;
// TODO Auto-generated constructor stub
}
#Override
public void onDraw(Canvas canvas)
{
for (int i = 0; i < pAll.length;i++)
{
canvas.drawCircle(200, 200, 100, pAll[i]);
}
}
}
If you want to draw the same circle with its color changing over the time (each 2 seconds as you mentionned) you should use an Handler
in order to create a timer and to switch the paint at each time it is called.
Do not forget to call the invalidate function inside your custom view, as this function ask the system to redraw the screen.