android application is exited when override function from custom view - android

I have a custom view and want to display it, however if I call the method from the custom view (setOnClickListener,...) the application will automatically exit, I don't know why and hope everyone answers.
public class MotionEventActivity extends AppCompatActivity{
#SuppressLint("ClickableViewAccessibility")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//MyView myView = new MyView(this);
setContentView(R.layout.motion_view);
MyView myView = findViewById(R.id.main);
myView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
}
}
And here is the code of the custom view:
public class MyView extends View {
public Paint paint = null;
public int radius = 82;
public List<CoordinateButton> arrButton = new ArrayList<CoordinateButton>();
MyView(Context context){
this(context, null);
}
public MyView(Context context, AttributeSet attributeSet) {
super(context);
arrButton.add(new CoordinateButton("S",(float)46.0 , (float) 37.0, 1, "#F08080", "#DC143C", "#F08080"));
arrButton.add(new CoordinateButton("H",(float)1866.0 , (float) 699.0, 4, "#F0E68C", "#FFFF00", "#F0E68C"));
paint = new Paint();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for(CoordinateButton button : arrButton){
paint.setColor(Color.parseColor(button.getColorButton()));
canvas.drawCircle(button.getXButton() + radius, button.getYButton() + radius, radius, paint);
paint.setColor(Color.BLACK);
paint.setTextSize(45);
paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(button.getTextButton(),button.getXButton() + radius, button.getYButton() + radius +15, paint);
}
}
}
And here is the code of the xml file:
<?xml version="1.0" encoding="utf-8"?>
<com.example.motionevent.MyView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MotionEventActivity">
</com.example.motionevent.MyView>

Related

Adding a Custom View as header of ListView

I have a custom view (a class extending View) that I'd like to add as a header of List View. Here's the code snippet:
public class MyActivity extends RoboListActivity {
...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View header = getLayoutInflater().inflate(R.layout.myactivity_apps_header, null);
getListView().addHeaderView(header);
...more code
}
But, I can't see anything. But, when I tried to add a non-custom view, it works. Am I missing something, please guide
Providing Complete Source Code
Custom View
public class SpaceCustomView extends View {
private Paint mPaint;
private Paint mTextPaint;
private final String mMessage = "Foo Bar";
private Rect mBounds;
public StorageSpaceCustomView(Context context) {
super(context);
initInput();
}
public StorageSpaceCustomView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
initInput();
}
public StorageSpaceCustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initInput();
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
}
#Override
public void onDraw(android.graphics.Canvas canvas) {
canvas.drawRect(30, 30, 800, 80, mPaint);
canvas.drawText(mMessage, 30, 60, mTextPaint);
}
private void initInput() {
mBounds = new Rect();
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mTextPaint = new Paint();
mTextPaint.setColor(Color.BLACK);
mTextPaint.setTextAlign(Paint.Align.LEFT);
mTextPaint.setTextSize(20);
mTextPaint.getTextBounds(mMessage, 0, mMessage.length(), mBounds);
}
}
Header Layout XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.mycompany.app.view.custom.SpaceCustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Activity Class
public class AppsActivity extends RoboListActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//add header and footer views
View header = getLayoutInflater().inflate(R.layout.activity_apps_header, null);
getListView().addHeaderView(header);
View footer = getLayoutInflater().inflate(R.layout.activity_pps_footer, null);
getListView().addFooterView(footer);
List<AppInfo> applicationList = Mycatalog.getPromotions();
AppListAdapter adapter = new AppListAdapter(this, applicationList);
setListAdapter(adapter);
}
private class AppListAdapter extends ArrayAdapter<AppInfo> {
public AppListAdapter(Activity activity, List<AppInfo> apps) {
super(activity, android.R.layout.simple_list_item_1, apps);
}
#Override
public boolean isEmpty(){
return false;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// if we weren't given a view, inflate one
if (null == convertView) {
convertView = getLayoutInflater()
.inflate(R.layout.activity_uninstall_apps, null);
}
return convertView;
}
}
}
Conclusion: I can see the footer but not the header.
ListView shows headers and footers only when it's Adapter's isEmpty() returns false.
So try setting an adapter that does that...

setting onClickListener on views drawn on a canvas

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>

How to draw a custom view inside a SurfaceView?

I am having trouble putting all the pieces together. I have 3 classes: DefaultActivity that extends Activity, MyView that extends SurfaceView, and ResistorView that extends a View.
What I want to know is how draw a resistor every time I click the button bAddResistor from the DefaultActivity class? Here are some parts from the 3 classes:
DefaultActivity.java
public class DefaultActivity extends Activity {
//MyView myView;
TextView myText;
ResistorView myResistor;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//myView = (MyView) findViewById(R.id.my_view);
//myView = new MyView(this, null);
//myResistor = new ResistorView(this);
//myView.setBackgroundColor(Color.WHITE);
//myView.setScrollContainer(true);
setContentView(R.layout.main);
final Button bAddResistor = (Button) findViewById(R.id.bAdd);
bAddResistor.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
Global.numberOfResistors++;
Log.d("ButtonADD", "Button Add has been clicked");
}
});
}
}
MyView.java
public class MyView extends SurfaceView implements SurfaceHolder.Callback {
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
getHolder().addCallback(this);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas c = holder.lockCanvas();
onDraw(c);
holder.unlockCanvasAndPost(c);
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
}
ResistorView.java
public class ResistorView extends View {
private Path mSymbol;
private Paint mPaint;
//...Override Constructors...
public ResistorView(Context context) {
super(context);
init();
}
public ResistorView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mSymbol = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth(2);
mPaint.setColor(-7829368);
mPaint.setStyle(Paint.Style.STROKE);
//...Your code here to set up the path,
//...allocate objects here, never in the drawing code.
mSymbol.moveTo(0.0F, 0.0F);
mSymbol.lineTo(0.0F, 50.0F);
mSymbol.lineTo(16.666666F, 58.333332F);
mSymbol.lineTo(-16.666666F, 75.0F);
mSymbol.lineTo(16.666666F, 91.666664F);
mSymbol.lineTo(-16.666666F, 108.33333F);
mSymbol.lineTo(16.666666F, 124.99999F);
mSymbol.lineTo(-16.666666F, 141.66666F);
mSymbol.lineTo(0.0F, 150.0F);
mSymbol.lineTo(0.0F, 200.0F);
mSymbol.offset(100.0F, 20.0F);
}
//...Override onMeasure()...
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//Use this method to tell Android how big your view is
setMeasuredDimension(50, 50);
}
//...Override onDraw()...
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(mSymbol, mPaint);
}
}
and the main.xml layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/RelativeLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:ignore="HardcodedText" >
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/RightLayout"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentRight="true"
android:background="#00000000"
android:orientation="vertical" >
<Button
android:id="#+id/bAdd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add RES" />
<Button
android:id="#+id/bDeleate"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Del RES" />
</LinearLayout>
<com.defaul.android.MyView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_toLeftOf="#id/RightLayout"
android:background="#ff000000" />
</RelativeLayout>
If I put the drawing code in MyView.onDraw it works fine, the resistor is drawn. What I want is to click a button and draw the resistor on the surface, so every time I click I want a resistor to be added to the surface view.
Probably I'm approaching this problem in the opposite direction. If anyone can point me in the right direction I would really appreciated it.
Since I could not find a way to do what I wanted with SurfaceView I just created a class that extends View and then just add that view to my main layout.
In case it might help someone, below is a simplified version of my code:
public class CircuitSolverActivity extends Activity {
/** Called when the activity is first created. */
RelativeLayout mLayout;
MyView mView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mLayout = (RelativeLayout)findViewById(R.id.elementContainer);
}
public void bAddView(View view){
mView = new MyView(context);
mView.setBackgroundColor(Color.TRANSPARENT);
mLayout.addView(mView);
}
MyView class:
public class ResistorView extends View {
public ResistorView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ResistorView(Context context){
super(context);
init();
}
private void init() {
mSymbol = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth(2);
mPaint.setColor(-7829368);
mPaint.setStyle(Paint.Style.STROKE);
mSymbol.moveTo(0.0F, 0.0F);
mSymbol.lineTo(0.0F, 50.0F);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(mSymbol, mPaint);
}

Cannot render an xml layout with LayoutInfalter. What I'm doing wrong?

I need to show a layout from xml file and draw some vector based image on top of that. If code below is executed then everything is shown but the layout. Why? What I'm doing wrong?
public class About extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//setContentView(R.layout.about);
setContentView(new GraphicsView(this));
}
public class GraphicsView extends View
{
public GraphicsView(Context context)
{
super(context);
}
#Override
protected void onDraw(Canvas canvas)
{
Context context;
context=getContext();
View aview;
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
aview = inflater.inflate(R.layout.about, null);
aview.draw(canvas);
Path circle = new Path();
Paint cPaint = new Paint();
cPaint.setColor(Color.LTGRAY);
circle.addCircle(150, 150, 100, Direction.CW);
canvas.drawPath(circle, cPaint);
cPaint.setColor(Color.RED);
canvas.drawTextOnPath("Some stupid text", circle, 0, 20, cPaint);
}
}
}
After inflating the View you need to measure it and lay it out to give it a size so it can be properly drawn. You should call aview.measure() and aview.layout() before calling aview.draw().
Note that you should NEVER inflate views from onDraw(). It is very expensive and wasteful. Similarly, you should NEVER create paints or paths inside onDraw().
There is an another answer from another forum:
FrameLayout:
public class About extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.about);
GraphicsView drawing = new GraphicsView(this);
FrameLayout container = (FrameLayout) findViewById(R.id.container);
container.addView(drawing);
}
public class GraphicsView extends View
{
public GraphicsView(Context context)
{
super(context);
}
#Override
protected void onDraw(Canvas canvas)
{
Path circle = new Path();
Paint cPaint = new Paint();
cPaint.setColor(Color.LTGRAY);
circle.addCircle(150, 150, 100, Direction.CW);
canvas.drawPath(circle, cPaint);
cPaint.setColor(Color.RED);
canvas.drawTextOnPath("Some stupid text", circle, 0, 20, cPaint);
}
}
}
And then here comes XML:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dip"
android:id="#+id/container">
<TextView
android:id="#+id/about_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/about_text" />
</FrameLayout>

It is possible to set the text of a "TextView" from within a class 'extends View'

I've insert a custom View called "disegno" inside a Layout xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?windowsBackground">
<it.package.myapp.Disegno
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/finestraDisegno"
android:isScrollContainer="true" />
<FrameLayout
android:layout_height="0dp"
android:layout_width="0dp"
...
<EditText
...
android:id="#+id/et_MOD_x">
</EditText>
Then I've implemented the extends View class for populate the custom layout:
package it.package.myapp;
import android.content.Context;
...
public class Disegno extends View {
public Disegno(Context context) {
this(context, null, 0); }
public Disegno(Context context, AttributeSet attrs) {
this(context, attrs, 0);
setContentView(R.layout.main); }
public Disegno(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
init(attrs); }
...
#Override
protected void onDraw(Canvas canvas) {
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);
// chiamo routine assi cartesiani
AssiCartesiani(canvas);
// chiamo routine polilinea
Polilinea(canvas); }
...
Now I would to set the text of the textView "et_MOD_x" by "findViewById(R.Id.et_MOD_x)" changing the code like this:
#Override
protected void onDraw(Canvas canvas) {
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);
// chiamo routine assi cartesiani
AssiCartesiani(canvas);
// chiamo routine polilinea
Polilinea(canvas);
EditText et_MOD_x = (EditText) findViewById(R.Id.et_MOD_x)
et_MOD_x.setText("abcd");
}
but without "setContentView(...)" is not possible!
Summing: I would to set the text of a "EditText" from within an "extends View" class. I'd to pointing to an external layout... mmmhh!
There is any way to do this?!
have a reference in your custom view
public class Disegno extends View {
private TextView textView;
public void setTextView(TextView tv){
textview = tv;
}
#Override
protected void onDraw(Canvas canvas) {
textview.setText("Your text here!")
}
}
in your Activity.onCreate()
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.my_layout);
EditText et_MOD_x = (EditText) findViewById(R.Id.et_MOD_x);
Disegno finestraDisegno = (Disegno)findViewById(R.Id.finestraDisegno);
finestraDisegno.setTextView(et_MOD_x) ;
}
May be this is not the right way but you can :
Get your editText in your activity and declare it as static.
public static EditText et_MOD_x;
et_MOD_x = (EditText) findViewById(R.Id.et_MOD_x)
and In your View class set the text by :
YourActivity.et_MOD_x.setText("abcd");
Hope it helps..

Categories

Resources