How to instantiate a view inside a Frame layout? - android

This is my MainActivity:
public class MainActivity extends Activity {
PieMenu pieMenu;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pieMenu = new PieMenu(getApplicationContext());
}
#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;
}
}
PieMenu:
public class PieMenu extends FrameLayout{
private Context _context;
public PieMenu(Context context) {
super(context);
_context = context;
// TODO Auto-generated constructor stub
}
public void addPieMenu(int x, int y){
Toast.makeText(_context, "text",Toast.LENGTH_LONG).show();
PieItem pieView = new PieItem(_context,x,y,2);
//FrameLayout.LayoutParams lyp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
//pieView.setLayoutParams(lyp);
addView(pieView);
invalidate();
}
}
PieItem.java:
public class PieItem extends View{
private final float x;
private final float y;
private final int r;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
public PieItem(Context context, float x, float y, int r) {
super(context);
mPaint.setColor(0xFFFF0000);
this.x = x;
this.y = y;
this.r = r;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(x, y, r, mPaint);
}
}
MainActivity.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"
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" />
</FrameLayout>
Everytime I touch the scree, the toast is being called but the circle isn't being instantiated. Where am I going wrong?

easiest way to fix this, add view in onCreate:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pieMenu = new PieMenu(getApplicationContext());
FrameLayout fl = (FrameLayout)findViewById(R.id.layout);
fl.addView(pieMenu);
}
and add id to your main activity xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >

You aren't adding pieMenu to any of the views in your layout (R.layout.activity_main)
What does your activity_main.xml look like?

You didn't add created PieMenu to activity layout. You need to call something like this in onCreate method:
view.addView(pieMenu);
Or add your PieMenu to you activity_main layout.

Related

Android - invalidate() doesn't call my onDraw in CustomView

I have an content_main.xml:
<LinearLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:showIn="#layout/activity_main">
<com.example.CustomView
android:id="#+id/customView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout >
In MainActivity.java, in onCreate I call the CustomView:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
customView = new CustomView(this, attributeSet);
customView.init();
}
And in CustomView, I have an onDraw:
#SuppressLint("DrawAllocation")
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLUE);
drawValidMoves(canvas, squareSize);
}
in MainActivity, the onTouch
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
int x = (int)event.getX();
int y = (int)event.getY();
String text = customView.isTouched(x, y, customView.getSquareSize());
Toast.makeText(this, text, Toast.LENGTH_LONG).show();
}
return super.onTouchEvent(event);
}
is calling an method from CustomView.java - isTouched that change some things in a matrix of drawed elements and after that, I'm making some:
setWillNotDraw(false);
invalidate();
but my game doesn't reach onDraw again...
If I'm calling in onCreate directly the CustomView, the invalidate works:
customView = new CustomView(this, attributeSet);
customView.init();
setContentView(customView);
but I don't have the toolbar anymore, and I need that
LATER EDIT:
content_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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/linearLayoutId"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:showIn="#layout/activity_main">
<com.example.clotz.CustomView
android:id="#+id/customView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout >
MainActivity.java - onCreate - I moved the data from init method into constructor and get rid of init.
public class MainActivity extends AppCompatActivity {
CustomView customView;
#SuppressLint("WrongViewCast")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
customView = findViewById(R.id.customView);
}
But customView is null now in onTouchEvent:
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
int x = (int)event.getX();
int y = (int)event.getY();
String text = customView.isTouched(x, y, customView.getSquareSize());
Toast.makeText(this, text, Toast.LENGTH_LONG).show();
}
return super.onTouchEvent(event);
}
#Mike M helped me with this and I put in content_main.xml the id of the linearLayout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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/linearLayoutId"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:showIn="#layout/activity_main">
<com.example.clotz.CustomView
android:id="#+id/customView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout >
in MainActivity.java - onCreate (I moved the data from init method into constructor and get rid of init) and I created the customview with findViewById(R.id.customView);
public class MainActivity extends AppCompatActivity {
CustomView customView;
#SuppressLint("WrongViewCast")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
customView = findViewById(R.id.customView);
}
And the problem was in CustomView.java, I forgot to pass attributeSet to the superclass:
public CustomView(Context context, AttributeSet attributeSet) {
super(context);
initializeMovedMatrix();
setInitialPositionForPieces();
// create the Paint to set its color
paint = new Paint();
piecesMoves = new PiecesMoves(this);
}
and putting it, combined with customView = findViewById(R.id.customView);
super(context, attributeSet);
Solved the problem.
Thanks again MikeM!
you cannot delete super.onDraw(canvas) in onDraw method.
#SuppressLint("DrawAllocation")
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.BLUE);
drawValidMoves(canvas, squareSize);
}

How to have text views that move along the progress bar

Context: I want to build a horizontal progress bar with some values and want to put some text that move along below this progress bar. So my final ideia is something like this (I already have the progress bar built I only left the text views below)
My current code is something like this:
This is my StackedHorizontalProgressBar class:
public class StackedHorizontalProgressBar extends ProgressBar {
private Paint paint;
int primary_progress, max_value;
public StackedHorizontalProgressBar(Context context) {
super(context);
init();
}
public StackedHorizontalProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
#Override public synchronized void setMax(int max) {
this.max_value = max;
super.setMax(max);
}
#Override public synchronized void setProgress(int progress) {
if (progress > max_value) {
progress = max_value;
}
this.primary_progress = progress;
super.setProgress(progress);
}
#Override public synchronized void setSecondaryProgress(int secondaryProgress) {
if ((primary_progress + secondaryProgress) > max_value) {
secondaryProgress = (max_value - primary_progress);
}
super.setSecondaryProgress(primary_progress + secondaryProgress);
}
private void init() {
paint = new Paint();
paint.setColor(Color.BLACK);
primary_progress = 0;
max_value = 100;
}
}
This is my Main Activity layout (that uses above class)
<android.support.constraint.ConstraintLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity">
<github.nisrulz.stackedhorizontalprogressbar.StackedHorizontalProgressBar
android:id="#+id/stackedhorizontalprogressbar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:progressDrawable="#drawable/stacked_horizontal_progress"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="16dp" />
</android.support.constraint.ConstraintLayout>
This is my MainActivity class:
public class MainActivity extends AppCompatActivity {
int max = 100;
int countPrimary = 20;
int countSecondary = 30;
StackedHorizontalProgressBar stackedHorizontalProgressBar;
TextView txt_primary, txt_secondary;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
stackedHorizontalProgressBar =
(StackedHorizontalProgressBar) findViewById(R.id.stackedhorizontalprogressbar);
stackedHorizontalProgressBar.setMax(max);
stackedHorizontalProgressBar.setProgress(countPrimary);
txt_primary.setText("Primary Value : " + countPrimary + "%");
stackedHorizontalProgressBar.setSecondaryProgress(countSecondary);
txt_secondary.setText("Secondary Value : " + countSecondary + "%");
}
}
I think I must use canvas for this, so if there is anyone with experience with this that can help me.
public class ProgressBarAvtivity extends AppCompatActivity {
ProgressBar progressBar;
TextView tvProgress;
int d = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_progress_bar_avtivity);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
progressBar.setProgress(d);
tvProgress = (TextView)findViewById(R.id.tvProgress);
tvProgress.setText(String.valueOf(d));
if (d > 40) {
tvProgress.setX(((width )* d / 100) - (d/2));
}
else {
tvProgress.setX(((width )* d / 100));
}
}}

Android Floating Button not showing

I try to make drawing page with canvas and add floating button in corner for some actions. But it is not appearing.
This is my classes
DrawView.java
public class DrawView extends View implements View.OnTouchListener {
private List<Point> points = new ArrayList<>();
private Paint paint = new Paint();
public DrawView(Context c) {
super(c);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
paint.setColor(Color.BLACK);
}
#Override
public void onDraw(Canvas canvas) {
for (Point point : points) {
canvas.drawCircle(point.x, point.y, 30, paint);
}
}
public boolean onTouch(View view, MotionEvent event) {
Point point = new Point();
point.x = event.getX();
point.y = event.getY();
points.add(point);
invalidate();
return true;
}}
And Main activity
public class DrawingPage extends AppCompatActivity {
private DrawView drawView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drawing_page);
drawView = new DrawView(getApplicationContext());
drawView.setBackgroundColor(Color.WHITE);
setContentView(drawView);
drawView.requestFocus();
}}
XML
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="reminder.com.picsartdrawing.DrawingPage">
<android.support.design.widget.FloatingActionButton
android:id="#+id/myFAB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#mipmap/ic_launcher"
app:elevation="4dp"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true" />
</RelativeLayout>
But floating button is not appearing, any solutions?
Screenshot
EDIT!!!
in Activity's onCreate method I have changed this, and now I have drawing canvas page with button.
RelativeLayout layout = (RelativeLayout) findViewById(R.id.layout);
drawView = new DrawView(getApplicationContext());
drawView.setBackgroundColor(Color.WHITE);
drawView.requestFocus();
assert layout != null;
layout.addView(drawView);
In onCreate() you replace 2 times with setContentView() the "main" view, so try with only this:
setContentView(R.layout.activity_drawing_page);
You need to add this in the onCreate method of your activity class:
FloatingActionButton fab = (FloatingActionButton) findViewById (R.id.fab);
fab.setOnClickListener (new View.OnClickListener () {
#Override
public void onClick (View view) {
Snackbar.make (view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction ("Action", null).show ();
}
});

How to add canvas to an extended View in Android?

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);
// ~
}

Adding view onto an activity

If I want to add a button in this class so that I can call the onclicklistener, how should I do it?
public class GameView extends View {
Path circle;
Paint cPaint;
Paint tPaint;
String z;
int i = 65, strt, arc, leftx, topy, rightx, bottomy, maxx, maxy;
boolean flag1, flag2, flag3;
double n1, n2;
int n, n3 = 180,n4,n5 = 90;
float f1 = 180, f2 = 90;
Button b1;
Random r = new Random();
RectF oval;
public GameView(Context context) {
super(context);
leftx = 0;
topy = 60;
rightx = 150;
bottomy = 120;
z = String.valueOf(Character.toChars(i));
cPaint = new Paint();
cPaint.setColor(Color.RED);
strt = 45;
arc = 315;
n1 = Math.random() * 600;
Log.d("random", z);
if (flag2 == false)
new DrawThread(this);
// cPaint.setStrokeWidth(2);
tPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
tPaint.setStyle(Paint.Style.FILL_AND_STROKE);
tPaint.setColor(Color.BLACK);
float scale = getResources().getDisplayMetrics().scaledDensity;
tPaint.setTextSize(20 * scale);
}
public void onSizeChanged(int w,int h,int oldh,int oldw) {
maxx = oldw;
maxy = oldh;
}
//#Override
protected void onDraw(Canvas canvas) {
// Drawing commands go here
oval = new RectF(leftx,topy,rightx,bottomy);
canvas.drawArc(oval, strt, arc, true, cPaint);
while (i < 90) {
canvas.drawText(String.valueOf(Character.toChars(i)),f1,f2, tPaint);
break;
}
}
}
RelativeLayout layout = (RelativeLayout) findViewById(R.id.relative_layout);
add the above below setContentView
setContentView(R.layout.activity_new_game);
RelativeLayout layout = (RelativeLayout) findViewById(R.id.relative_layout);
You need to set the layout using setContentView and then initialize views.
Note you can findViewById of the current view hierarchy set to the activity
Edit:
Example: This is an example. I don't see why it won't work if you do similar as below.
<RelativeLayout 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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".NewGame"
android:id="#+id/relative_layout"
>
<Button
android:id="#+id/prev_button"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/next_button"
android:layout_alignBottom="#+id/next_button"
android:layout_centerHorizontal="true"
android:text="stop_label" />
<Button
android:id="#+id/next_button"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginRight="20dp"
android:layout_toLeftOf="#+id/prev_button"
android:text="start_label" />
<RelativeLayout
android:layout_width="wrap_content"
android:id="#+id/rl"
android:layout_below="#+id/prev_button"
android:layout_height="wrap_content"
>
</RelativeLayout>
</RelativeLayout>
Activity
public class MainActivity extends Activity {
private Button btn1;
private EditText edt1, edt2, edt3, edt4 ,edt5, edt6;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyView mv = new MyView(this);
setContentView(R.layout.activity_main);
RelativeLayout layout= (RelativeLayout) findViewById(R.id.rl);
layout.addView(mv);
}
class MyView extends View
{
public MyView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.drawColor(Color.RED);
}
}
}
snapshot
You need to inflate your view before trying to find your relative layout. Try :
RelativeLayout layout;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
gameview=new GameView(this);
setContentView(R.layout.activity_new_game);
layout = (RelativeLayout) findViewById(R.id.relative_layout);
//LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//view = mInflater.inflate(R.layout.activity_new_game, gameview, true);
layout.addView(gameview);
}
RelativeLayout layout = (RelativeLayout) findViewById(R.id.relative_layout);
you can't call findViewById before setContentView. Move
RelativeLayout layout = (RelativeLayout) findViewById(R.id.relative_layout);
after setContentView(R.layout.activity_new_game);
you didn't initialize layout in your code so First initialize layout after setContentView then add view to your layout
RelativeLayout layout;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_game);
//Initialize game view
GameView gameview=new GameView(this);
//initialize layout
layout = (RelativeLayout) findViewById(R.id.relative_layout);
//adding game view to layout
layout.addView(gameview);
}
Edit:
initializing like this before setContentView
RelativeLayout layout = (RelativeLayout) findViewById(R.id.relative_layout);
is wrong approach you must initialize views only after setContentView like the above code

Categories

Resources