When I try to create my GameView, I get an error "function call expected".
in my Main activity:
GameView gv = GameView(this, null);
public class GameView extends View {
private Drawable mCustomImage;
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
mCustomImage = context.getResources().getDrawable(R.drawable.bg);
}
protected void onDraw(Canvas canvas) {
Rect imageBounds = canvas.getClipBounds(); // Adjust this for where you want it
mCustomImage.setBounds(imageBounds);
mCustomImage.draw(canvas);
}
}
}
How do I create this dynamically?
I'm trying to add a view to my activity. The GameView will then control the position of its subviews programmatically.
This will make scene
I made some new changes in your GameView class. Below is copy of new GameView class.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
public class GameView extends View {
private Context mContext;
private Drawable mCustomImage;
public GameView(Context context) {
super(context);
mContext = context;
mCustomImage = ContextCompat.getDrawable(context, R.mipmap.ic_launcher);
}
public GameView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
mContext = context;
mCustomImage = ContextCompat.getDrawable(context, R.mipmap.ic_launcher);
}
public GameView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
mCustomImage = ContextCompat.getDrawable(context, R.mipmap.ic_launcher);
}
public GameView(Context context, #Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mContext = context;
mCustomImage = ContextCompat.getDrawable(context, R.mipmap.ic_launcher);
}
#Override
protected void onDraw(Canvas canvas) {
Rect imageBounds = canvas.getClipBounds();
mCustomImage.setBounds(imageBounds);
mCustomImage.draw(canvas);
}
}
Adding it through xml inside activity.
<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">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<GameView
android:layout_width="50dp"
android:layout_height="50dp" />
</LinearLayout>
</ScrollView>
Output
Adding it through code in activity
public class CustomActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_draw_line);
initialiseView();
}
private void initialiseView() {
LinearLayout mLinearLayout = (LinearLayout) findViewById(R.id.linearLayout);
GameView mGameView = new GameView(this);
mLinearLayout.addView(mGameView);
}
}
Output
EDIT
If you want to set parameters while adding it pragmatically then initialiseView method will be like
private void initialiseView() {
LinearLayout mLinearLayout = (LinearLayout) findViewById(R.id.linearLayout);
GameView mGameView = new GameView(this);
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(50, 50);
mGameView.setLayoutParams(layoutParams);
mLinearLayout.addView(mGameView);
}
Output :
GameView is a class, not a method, so you must call new to use them,
try this:
GameView gv = new GameView(this, null);
public class GameView extends View {
private Drawable mCustomImage;
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
mCustomImage = context.getResources().getDrawable(R.drawable.bg);
}
....
Use new GameView(this, null); inside onCreate of your activity to create a new instance of your view.
Then use the method setContentView(View) to use it in your activity.
public class MainActivity extends AppCompatActivity{
private GameView gameView;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gameView = new GameView(this, null);
setContentView(gameView);
//other code
}
//other methods
}
Related
My .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"
tools:context="com.example.eleizo.firstapplication.MainActivity"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="#+id/topRL">
</RelativeLayout>
....
I added my custom ImageView object in RelativeLayout topRL.addView(map); Constructor of the custom ImageView is:
public CustomImageView(Context context) {
super(context);
init();
}
public CustomImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM,1);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,1);
setBackgroundColor(Color.BLUE);
this.setWillNotDraw(false);
setLayoutParams(params);
}
On create:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(com.example.eleizo.firstapplication.R.layout.activity_main);
RL = (RelativeLayout) findViewById(R.id.topRL);
Context context = getApplicationContext();
map = new CustomImageView(context);
RL.addView(map,map.params);
But RelativeLayout.ALIGN_PARENT_RIGHT,RelativeLayout.ALIGN_PARENT_BOTTOM doesn't work: After map.setImageBitmap(input); I see my image in left-top corner.
I want bottom-right corner of the image is on botton-right corner of the RelativeLayout independently of size of the image.
Where did I make the mistake?
You have your addRule wrong. Check this links:
a) https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams.html#addRule(int)
b) https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams.html#addRule(int, int)
If you want to pass multiple rules you have to call consecutively:
.addRule(RelativeLayout.ALIGN_PARENT_RIGHT)
.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
If you want a subject that represents the value of the param to set you have to use the 2 parameters method addRule(int, int/bool).
Here is the solution which worked for me.
CustomeImageView.java
public class CustomImageView extends AppCompatImageView {
public CustomImageView(Context context) {
super(context);
init();
}
public CustomImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
setLayoutParams(params);
}
}
main_activity.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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.icpl.threadsample.MainActivity"
tools:showIn="#layout/activity_main">
<RelativeLayout
android:id="#+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/black"/>
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.relativeLayout);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
CustomImageView imageView = new CustomImageView(MainActivity.this);
imageView.setImageResource(R.mipmap.ic_launcher);
relativeLayout.addView(imageView);
}
});
}
}
Checkout this Answer as well.
I have a custom CircleButton class:
public class CircleButton extends ImageView {
private int radius;
private int x;
private int y;
public CircleButton(Context context) {
super(context);
constructorTask();
}
public CircleButton(Context context, AttributeSet attrs) {
super(context, attrs);
constructorTask();
}
public CircleButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
constructorTask();
}
public CircleButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
constructorTask();
}
private void constructorTask() {
x = 300;
y = 300;
radius = 100;
}
#Override
public void setPressed(boolean pressed) {
super.setPressed(pressed);
Log.i("Button Logger","Button Pressed");
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(x, y, radius, GameView.green);
Log.i("Drawing status", "CircleButton Drawing...");
}
}
I have a single activity. This activity contains a relative layout with a single custom view.
Here is the custom view:
public class GameView extends View {
public static Paint green = new Paint();
public GameView(Context context) {
super(context);
green.setARGB(255,0,255,0);
}
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
green.setARGB(255, 0, 255, 0);
}
public GameView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
green.setARGB(255, 0, 255, 0);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i("GameView Draw Status","Drawing...");
Main.testButton.invalidate();
invalidate();
}
}
And here is the activity code:
public class Main extends AppCompatActivity {
public static CircleButton testButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testButton = new CircleButton(getApplicationContext());
makeFullScreen();
RelativeLayout screenLayout = (RelativeLayout) findViewById(R.id.screenLayout);
screenLayout.addView(testButton);
}
private void makeFullScreen() {...}
}
For some reason my testButton is not being drawn. Why is it not being drawn?
EDIT ONE: Here is the XML I have.
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="0dp"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:paddingTop="0dp"
tools:context="com.example.vroy.customcirclebuttontest.Main"
android:id="#+id/screenLayout">
<com.example.vroy.customcirclebuttontest.GameView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black"
android:id="#+id/gameScreen" />
</RelativeLayout>
EDIT TWO: I did some further debugging by adding a normal button to the relative layout and it worked fine.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testCircleButton = new CircleButton(getApplicationContext());
makeFullScreen();
testButton = new Button(getApplicationContext());
testButton.setX(100);
testButton.setY(100);
testButton.setText("HELLO WORLD");
RelativeLayout screenLayout = (RelativeLayout) findViewById(R.id.screenLayout);
screenLayout.addView(testCircleButton);
screenLayout.addView(testButton);
Log.i("Button Status","Adding Button To Layout");
}
For some reason by circleButton is not working but a normal button is.
You are not specifying the size of the View (layout_width and layout_height), and thus your view is getting rendered inside a 0px by 0px space and thus invisible.
You can set those programatically using LayoutParams before adding your views to the layout.
For example with absolute size:
testButton.setLayoutParams(new ViewGroup.LayoutParams(100,100));
Although keep in mind the difference between px and dip. You would probably want to set the values using your internal radius attribute instead of harcoding them.
I have a custom ImageView class (I don't think the code in the class matters but I'll include it here anyway incase it is needed):
package com.example.vroy.customcirclebuttontest;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;
public class CircleButton extends ImageView {`
private int radius;
private int x;
private int y;
public CircleButton(Context context) {
super(context);
constructorTask();
}
public CircleButton(Context context, AttributeSet attrs) {
super(context, attrs);
constructorTask();
}
public CircleButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
constructorTask();
}
public CircleButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
constructorTask();
}
private void constructorTask() {
x = 300;
y = 300;
radius = 100;
}
#Override
public void setPressed(boolean pressed) {
super.setPressed(pressed);
Log.i("Button Logger","Button Pressed");
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(x, y, radius, GameView.green);
Log.i("Drawing status", "CircleButton Drawing..." + " " + Integer.toString(this.x) + "," + Integer.toString(this.y));
}
}
I declare a instance of this class in my activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testCircleButton = new CircleButton(getApplicationContext());
makeFullScreen();
testCircleButton.getLayoutParams().width = 200;
testCircleButton.getLayoutParams().height = 200;
RelativeLayout screenLayout = (RelativeLayout) findViewById(R.id.screenLayout);
screenLayout.addView(testCircleButton);
Log.i("Button Status","Adding Button To Layout");
}
However when I do this I get a "null pointer" exception.
How can I fix this?
It's because your testCircleButton is not attached to the Activity. It has no LayoutParams if it's not added to any parent.
Use
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(200, 200) // I'm not sure about constructor arguments.
testCircleButton.setLayoutParams(lp);
Use different LayoutParams if your root layout is different(FrameLayout etc).
I have 3 views:
GLSurfaceView
Custom SurfaceView
View
The GLSurfaceView is at the bottom
The Custom SurfaceView should be above and on the top
The View is above and on the bottom
This is my code:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity {
GameGlSurfaceView gameGlSurfaceView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gameGlSurfaceView = new GameGlSurfaceView(this);
setContentView(gameGlSurfaceView);
View hudView = getLayoutInflater().inflate(R.layout.activity_main, null);
addContentView(hudView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));
View inpudPadView = getLayoutInflater().inflate(R.layout.input_pad, null);
LinearLayout.LayoutParams inpudPadViewParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
inpudPadViewParams.gravity = Gravity.TOP;
addContentView(inpudPadView, inpudPadViewParams);
}
}
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class SurfacePanel extends SurfaceView implements SurfaceHolder.Callback {
Context context;
Bitmap bitmapTest;
MyThread mythread;
public SurfacePanel(Context ctx, AttributeSet attrSet ) {
super(ctx, attrSet);
context = ctx;
bitmapTest = Bitmap.createBitmap(200, 100, Bitmap.Config.ARGB_8888);
bitmapTest.eraseColor(Color.TRANSPARENT);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
}
void doDraw(Canvas canvas) {
canvas.drawColor(Color.GREEN);
canvas.drawBitmap(bitmapTest, 50, 10, null);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mythread = new MyThread(holder, context,this);
mythread.setRunning(true);
mythread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mythread.setRunning(false);
boolean retry = true;
while(retry) {
try {
mythread.join();
retry = false;
}
catch(Exception e) {
}
}
}
}
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="de.batechniks.surfaceviewtest.MainActivity">
<de.batechniks.surfaceviewtest.SurfacePanel
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/textView"/>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:baselineAligned="false"
xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="left">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/bt_down"
android:src="#mipmap/ic_launcher"
android:layout_gravity="bottom"/>
</LinearLayout>
The result is: I can see the GLSurfaceView and i can see the view above on the bottom.
On the top, i only see the textview "Large Text". The SurfaceView is not shown.
When i uncomment setContentView(gameGlSurfaceView), the SurfaceView is shown.
The main problem is to show the SurfaceView, the second problem will be to get the SurfaceView transparent.
Thanks a lot
You need to call the method
this.setZOrderOnTop(true);
in your constructors.
It's recommended to do constructors in custom views like this
public SurfacePanel (Context context) {
super(context);
init();
}
public SurfacePanel (Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SurfacePanel (Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
#TargetApi(21)
public SurfacePanel (Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
if(!isInEditMode()) {
this.setZOrderOnTop(true);
}
}
Why I can not put and see a custom view in a layout?
public class MainActivity extends Activity {
A a;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
a = (A) findViewById(R.id.a);
setContentView(a);
}
class A extends View {
Paint paint;
A(Context context) {
super(context);
paint = new Paint();
}
#Override
protected void onDraw(Canvas canvas) {
paint.setAntiAlias(true);
paint.setColor(Color.RED);
canvas.drawRect(10, 20, 60, 100, paint);
}
}
}
And please see the following image:
View A is an inner class of the Activity class, so the defination in the layout file is a little different.
Use this pattern:
<view class="{package}.{ParentClass}${innerClass}" />
In your case:
<view class="com.example.tec.test.MainActivity$A" />
Notice it's lowercase "view" not "View". And the inner class A should be declared as "public static" like this:
public class MainActivity extends Activity {
// Activity's methods
public static class A extends View {
public A(Context context) {
this(context, null);
}
public A(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public A(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
// A's methods
}
}
Override the below constructor on your view class and see if it works. When you include the view in xml you need to include the xml constructor in the view.
View(Context context, AttributeSet attrs)
public A(Context context, AttributeSet attrs) {
super(context, attrs);
}
public A(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
I solved my problem using your help.Thank you. The following code is for other questioner.
<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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<view class="com.example.tec.test.A"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/a"
/>
</RelativeLayout>
And the following java code:
public class MainActivity extends Activity {
A a;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
a= (A) findViewById(R.id.a);
a = new A(this);
setContentView(a);
}
}
class A extends View {
Paint paint;
public A(Context context) {
super(context);
}
public A(Context context, AttributeSet attrs) {
super(context, attrs);
}
public A(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
paint = new Paint();
paint.setColor(Color.RED);
canvas.drawRect(10, 20, 60, 70, paint);
}
}