I hame class GameManager(),
int class variable:
public GameView view;
it's class constructor:
public GameManager (GameView view)
{
this.view = view;
}
in the class GameView I create :
private GameManager gameLoopThread;
....
public GameView(Context context) {
super(context);
gameLoopThread = new GameView(this);// HERE IS ERROR ;
I dont know why it want to change gameLoopThread to GameView() type.
gameLoopThread = new GameManager(this);
Related
I want to transfer 2 float values and 1 boolean value from my MainActivity class to MyCanvas class (which is a class extends View)? Is this possible?
I know this a newbie question, but everything that I found told to use Intent and Bundle, or to use only Bundle.setArguments(), but apparently, none of them work for a View class.
Thank you.
EDIT 1
This is my MainActivity
public class MainActivity extends AppCompatActivity {
private MyCanvas myCanvas;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myCanvas = (MyCanvas) findViewById(R.id.canvas);
}
public void btnCalcularOnClick(View v) {
TextView xResultado = (TextView) findViewById(R.id.xResultado);
TextView yResultado = (TextView) findViewById(R.id.yResultado);
EditText txtX = (EditText) findViewById(R.id.txtX);
EditText txtY = (EditText) findViewById(R.id.txtY);
//Comeco da Matematica
float x = Float.parseFloat(txtX.getText().toString());
float y = Float.parseFloat(txtY.getText().toString());
float xResult = 5 * x;
float yResult = 35 * y;
boolean buttonState = true;
}
}
MyCanvas class is like that
public class MyCanvas extends View {
Paint myPaint;
public MyCanvas(Context context, AttributeSet attrs) {
super(context, attrs);
myPaint = new Paint();
}
#Override
public void onDraw(Canvas myCanvas) {
super.onDraw(myCanvas);
myPaint.setColor(Color.BLACK);
myPaint.setStrokeWidth(3);
float cx, cy;
boolean buttonState2;
}
}
In this case, I want to transfer:
xResult (MainActivity) -> cx (MyCanvas)
yResult (MainActivity) -> cy (MyCanvas)
buttonState (Main Activity) -> buttonState2 (myCanvas)
You can use setters to set the desired values in your MyCanvas class.
Create methods in your MyCanvas class like this.
public class MyCanvas extends View {
private float cx, cy;
private boolean buttonState2;
...
public void setResults(float xResult, float yResult) {
cx = xResult;
cy = yResult;
}
public void setButtonState(boolean state) {
buttonState2 = state;
}
}
Then in your activity class
public class MainActivity extends AppCompatActivity {
private MyCanvas myCanvas;
...
public void btnCalcularOnClick(View v){
TextView xResultado = (TextView)findViewById(R.id.xResultado);
TextView yResultado = (TextView)findViewById(R.id.yResultado);
EditText txtX= (EditText)findViewById(R.id.txtX);
EditText txtY= (EditText)findViewById(R.id.txtY);
//Comeco da Matematica
float x = Float.parseFloat(txtX.getText().toString());
float y = Float.parseFloat(txtY.getText().toString());
float xResult = 5 * x;
float yResult = 35 * y;
boolean buttonState = true
myCanvas.setResults(xResult, yResult);
myCanvas.setButtonState(buttonState);
}
}
Create static variable and use it in your MyCanvas class.
In MainActvity:-
public static float var1 = 1.0f;
public static float var2 = 2.0f;
public static boolean var3 = true;
And in your MyCanvas class:-
private float var1InCanvas = MainActivity.var1;
private float var2InCanvas = MainActivity.var2;
private float var3inCanvas = MainActivity.var3;
I created some custom component based on ConstraintLayout in Android Studio. First I created base abstract class called MyButton where I do some basic stuff (e.g. get references to my components). Next I created derived class called MySpecialButton that extends MyButton, but I have strange behavior when I attach onClickListener to my Button, that is a part of my custom component, and call method that modify element (reference) that exists only in MySpecialButton from onClickListener.
In a present code, when i try call setImage() from onClickListener, this end up with log: E/NULL: ImageView reference is null! which means that from point of view onClickListener, reference vImageViev is null, however it is initialized in inflateView call. But when I call setImage() not from onClickListener but directly from init() method after inflateView(R.layout.my_special_button) everything is OK.
Also when I move protected ImageView vImageView = null; declaration from MySpecialButton to MyButton everything is OK.
This is my MyButton class:
public abstract class MyButton extends ConstraintLayout
{
protected Context context = null;
protected View rootView = null;
protected Button vButton = null;
protected Switch vSwitch = null;
public MyButton(Context context)
{
super(context);
this.context = context;
init();
}
public MyButton(Context context, AttributeSet attrs)
{
this(context);
}
protected abstract void init();
protected void inflateView(int res)
{
rootView = inflate(context, res, this);
vButton = (Button)rootView.findViewById(R.id.vButton);
vSwitch = (Switch)rootView.findViewById(R.id.vSwitch);
}
}
and this is my MySpecialButton class:
public class MySpecialButton extends MyButton
{
protected ImageView vImageView = null;
public MySpecialButton(Context context)
{
super(context);
}
public MySpecialButton(Context context, AttributeSet attr)
{
this(context);
}
#Override
protected void inflateView(int res)
{
super.inflateView(res);
vImageView = (ImageView)rootView.findViewById(R.id.vImageView);
}
protected void init()
{
inflateView(R.layout.my_special_button);
vButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
setImage();
}
});
}
protected void setImage()
{
if(vImageView == null)
Log.e("NULL", "ImageView reference is null!");
else
vImageView.setImageResource(R.drawable.ic_window);
}
}
What's going on? What I should do to be able call setImage() from onClickListener without null reference?
I think you are doing wrong super calls in your constructors:
This
public MySpecialButton(Context context, AttributeSet attr)
{
this(context);
}
Should be:
public MySpecialButton(Context context, AttributeSet attr)
{
super(context, attr);
}
Same for the other class. And move your custom init in a different function you call from each constructor.
thats because the setOnClickLisnter is called for the base class(which is ConstraintLayout) since you are not override it in the sub-class where the ImageView is not accessible.
try this:
public abstract class MyButton extends ConstraintLayout
{
protected Context context = null;
protected View rootView = null;
protected Button vButton = null;
protected Switch vSwitch = null;
//...
#Override
public void setOnClickListener(#Nullable OnClickListener l) {
vButton.setOnClickLisnter(l);
}
}
I'm using PagerAdaper for image slide in my app. I want to add listener on it mean if the image show when i click on it it say something. let suppose i have an image of apple now i want to add listener on it when i click on it it say apple. i want to add the same on all raw files.
package com.example.slider;
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
public class ImageAdapter extends PagerAdapter {
private Context mcontext;
private int[] myImages = new int[] {R.raw.one , R.raw.two, R.raw.three,
R.raw.four , R.raw.five , R.raw.six, R.raw.seven, R.raw.eight,
R.raw.nine, R.raw.ten, R.raw.eleven, R.raw.twele , R.raw.thirteen, R.raw.fourteen,
R.raw.fifteen, R.raw.one_image, R.raw.two_image,
R.raw.three_image, R.raw.four_image, R.raw.five_image,
R.raw.six_image, R.raw.seven_image};
ImageAdapter(Context context){
mcontext = context;
}
#Override
public int getCount() {
return myImages.length;
}
#Override
public boolean isViewFromObject(View view, Object o) {
return view == o;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageView = new ImageView(mcontext);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setImageResource(myImages[position]);
container.addView(imageView,0);
return imageView;
}
#Override
public void destroyItem(ViewGroup container, int position,Object object) {
container.removeView((ImageView)object);
}
}
There are several different possible solutions. One way to connect each view with its image resource using a HashMap.
public class ImageAdapter extends PagerAdapter {
private Context mcontext;
private int[] myImages = new int[] {R.raw.one , R.raw.two, R.raw.three,
R.raw.four , R.raw.five , R.raw.six, R.raw.seven, R.raw.eight,
R.raw.nine, R.raw.ten, R.raw.eleven, R.raw.twele , R.raw.thirteen, R.raw.fourteen,
R.raw.fifteen, R.raw.one_image, R.raw.two_image,
R.raw.three_image, R.raw.four_image, R.raw.five_image,
R.raw.six_image, R.raw.seven_image};
ImageAdapter(Context context){
mcontext = context;
}
private HashMap<View, Integer> viewToImageResource = new HashMap<>();
private View.OnClickListener clickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
Integer clickedImageResource = viewToImageResource.get(v);
// Do something with clickedImageResource
}
};
#Override
public int getCount() {
return myImages.length;
}
#Override
public boolean isViewFromObject(View view, Object o) {
return view == o;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageView = new ImageView(mcontext);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setImageResource(myImages[position]);
container.addView(imageView,0);
viewToImageResource.put(container, myImages[position]);
container.setOnClickListener(clickListener);
return imageView;
}
#Override
public void destroyItem(ViewGroup container, int position,Object object) {
container.removeView((ImageView)object);
}
}
I have an Adapter (A ViewHolder) Class, and when a Button is pressed I'd like to update a TextView of the Home() activity, preferrably without launching the activity immediatly.
The code in the Adapter:
public class GameViewAdapter extends RecyclerView.Adapter<GameViewAdapter.GameViewHolder> {
public static Object OnItemClickListener;
private ArrayList<GameItem> mGameList;
private OnItemClickListener mListener;
public static MyCallback callback;
public GameViewAdapter(ArrayList<GameItem> mGameList, GameViewAdapter.OnItemClickListener mListener, MyCallback callback) {
this.mGameList = mGameList;
this.mListener = mListener;
this.callback = callback;
}
#Override
public GameViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
Context context = viewGroup.getContext();
View v = LayoutInflater.from(context).inflate(R.layout.game_entry, viewGroup, false);
GameViewHolder GVH = new GameViewHolder(v, mListener);
return GVH;
}
#Override
public void onBindViewHolder(#NonNull GameViewHolder gameViewHolder, int position) {
gameViewHolder.bind(mGameList.get(position));
}
#Override
public int getItemCount() {
return mGameList.size();
}
class GameViewHolder extends RecyclerView.ViewHolder {
private ImageView itemCover;
private TextView itemTitle;
private TextView itemDescription;
private PopupWindow popupWindow;
private ImageView popUpImage;
private TextView PopUpTitle;
private EditText customAmount;
private Button add;
private Button addcustom;
private Button exit;
public GameViewHolder(View itemView, GameViewAdapter.OnItemClickListener mListener) {
super(itemView);
setupViews(itemView);
}
public void bind(final GameItem gameItem) {
Glide.with(this.itemCover).load(gameItem.getCover()).into(this.itemCover);
this.itemTitle.setText(gameItem.getTitle());
this.itemDescription.setText(gameItem.getDescription());
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showPopUp(itemView, gameItem);
}
});
}
private void setupViews(View itemView) {
addcustom = itemView.findViewById(R.id.addcustom);
popUpImage = itemView.findViewById(R.id.popupimg);
PopUpTitle = itemView.findViewById(R.id.popuptitle);
customAmount = itemView.findViewById(R.id.gameamount);
itemCover = itemView.findViewById(R.id.GameCover);
itemTitle = itemView.findViewById(R.id.GameTitle);
itemDescription = itemView.findViewById(R.id.GameAmount);
exit = itemView.findViewById(R.id.exit);
}
private void showPopUp(final View itemView, final GameItem gameItem) {
//Declaration
final View popupView = LayoutInflater.from(itemView.getContext()).inflate(R.layout.popup, null);
final PopupWindow popupWindow = new PopupWindow(popupView, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
final ImageView popupItemCover = popupView.findViewById(R.id.popupimg);
final TextView popupItemTitle = popupView.findViewById(R.id.popuptitle);
//Set Data
Glide.with(popupItemCover).load(gameItem.getCover()).into(popupItemCover);
popupItemTitle.setText(gameItem.getTitle());
popupWindow.showAtLocation(popupView, Gravity.CENTER, 0, 0);
//ExitButton
exit = popupView.findViewById(R.id.exit);
exit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
popupWindow.dismiss();
}
});
add = popupView.findViewById(R.id.addaverage);
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
callback.onDataChanged(Integer.valueOf(gameItem.getTime()));
Toast.makeText(popupView.getContext(), String.valueOf(gameItem.getTime()), Toast.LENGTH_SHORT).show();
}
});
}
}
public interface MyCallback {
void onDataChanged(Integer gameTime);
}
public interface OnItemClickListener {
void onGameClick(int position);
}
}
And I have implemented this in the Main Activity:
public void onDataChanged(int gameTime) {
// it will fire when you call your callback.onDataChanged(); in your adapter
// here can change your textview
GameTime.setText(Integer.valueOf(gameTime));
}
}
I've tried to use BroadcastReceiver as well, with no success.
Thank you!
EDIT:
When adding the callback my App crashes with following traceback:
java.lang.NullPointerException: Attempt to invoke interface method 'void com.reogen.gametime.Adapters.GameViewAdapter$MyCallback.onDataChanged(java.lang.String)' on a null object reference
at com.reogen.gametime.Adapters.GameViewAdapter$GameViewHolder$3.onClick(GameViewAdapter.java:127)
Line 127 is: callback.onDataChanged(Integer.valueOf(gameItem.getTime()));
You can create observable like:
in your Adapter create:
public interface IMyCallback {
void onDataChanged(int gameTime);
}
Global field in Adapter:
private IMyCallback callback
Inside constructor of Adapter
public MyAdapter(... , IMyCallback callback) {
...
this.callback = callback;
}
Now your activity make implements IMyCallback and override method onDataChanged.
And when you create your adapter send as callback YourActivity.this.
finnaly you need to make like:
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
callback.onDataChanged(Integer.valueOf(gameItem.getTime()));
}
after this call you will get update in your override method onDataChanged in your activity class. enjoy
------------ Update -----------
in your activity, when you will implements interface you will get method like
#Override
public void onDataChanged(int gameTime) {
// it will fire when you call your callback.onDataChanged(); in your adapter
// here can change your textview
textview.setText(String.valueOf(gameTime));
}
I have created a custom ImageButton that will be used to change direction of objects in a simple game. The button is not responding when I click/touch it.
I have tried setOnTouchListener and setOnClickListener but nothing happens.
CustomButton:
public class CustomButton extends ImageButton {
private Bitmap bitmap;
public CustomButton(Context context, int resource) {
super(context);
setClickable(true);
bitmap = BitmapFactory.decodeResource(context.getResources(), resource);
}
public Bitmap getBitmap() {
return bitmap;
}
GameView:
public class GameView extends SurfaceView implements Runnable {
volatile boolean playing;
private Thread gameThread = null;
private CustomButton mLeftButton;
private Player player;
private Paint paint;
private Canvas canvas;
private Bitmap bitmap;
private SurfaceHolder surfaceHolder;
public GameView(Context context, int screenX, int screenY) {
super(context);
mLeftButton = new CustomButton(context, R.drawable.boom);
mLeftButton.setImageBitmap(mLeftButton.getBitmap());
mLeftButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getContext(),"It worked",Toast.LENGTH_LONG).show();
}
});
player = new Player(context, screenX, screenY);
surfaceHolder = getHolder();
paint = new Paint();
}
#Override
public void run() {
while (playing) {
update();
draw();
control();
}
}
private void update() {
player.update();
}
private void draw() {
if (surfaceHolder.getSurface().isValid()) {
canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(player.getBitmap(), player.getX(), player.getY(), paint);
canvas.drawBitmap(mLeftButton.getBitmap(), 20, 20, paint);
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
You create your button but not link it to the current layout.
In the draw method you simply draw it's image without adding its functionality to the SurfaceView, that way your button functionality is not used.
I'd suggest to create your base xml layout in a way where the button is over your surfaceview (with a RelativeLayout or a FrameLayout e.g.), then where you setup your Activity you'd setup up the onclicklistener for the button and wire it to the containing view.