Closing a view class and opening another view class - java

I call a view class from my activity. Then the view class calls the same activity. Here is the problem, once the activity comes back up, it won't register any more button pushes.(I'm trying to call another view class. Here is some code:
View Class
public class AnimationView extends View {
Activity myActivity;
//...
public AnimationView(Context context, Activity activity) {
super(context);
//...
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//...
myActivity.setContentView(R.layout.activity_home);
}
}
Home Activity
public class HomeActivity extends AppCompatActivity {
private AnimationView mDrawViewA;
///...
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
mDrawViewA = new AnimationView(this,this);
start = (Button) findViewById(R.id.startButton);
//...
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//...
setContentView(mDrawViewA);
//calls more views
//......
});
}
I realize now maybe I should have been calling the view classes in different activities, but I would very much like a get all the view classes working within the same activity.

The problem is you're calling setContentView every time you press the "start" button. This method will overwrite the current layout (if any) with the new value you're setting.
What you can do to get the result you're expecting, which, from what I understand, is to add a new AnimationView to your current layout on every button click, you can try something like this:
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AnimationView animationView = new AnimationView(getApplicationContext());
// I'm using ConstraintLayout as an example, since I don't know exactly what layout you're using
ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
// Set the layout params the way you want
addContentView(animationView, params); // This is where the magic happens
}
});
In short, addContentView is the method you should use when you want to add new views into your activity's root layout.
PS.: It's a terribly bad practice to let the views "know" the activity controlling it. It's always the opposite way around: the activity/fragment knows the view(s) it's controlling.

Related

How to access setOnClickListener of a button in custom view in android?

I am very new to Android Development and this is my first Android App.
Here is how my MainActivity layout looks like:
And this is the Component Tree of the MainActivity
The gridView is a custom view and I have a resetGrid function in it which looks something like this
public class GridView extends View {
resetGird(){
// stuff that resets grid;
}
}
Here is the problem I am facing:
I can access the setOnClickListener of the reset button in the MainActivity file but not in the GridView file where the resetGrid function is located.
resetButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(PathFind.this, "reset", Toast.LENGTH_SHORT).show();
}
});
I want to access this setOnClickListener of the reset button in the GridView file also and call the resetGrid function whenever the button is pressed.
Not only that, my plan is to use all the controls listed in the image (start button, diagonal checkbox, speed slider) to control the GridView. But I can't seem to find a way to do that.
All the controls are available in the main_activity but I can't use them in the GridView.
You are in the right way.
The "trick" is to save GridView's instance in a MainActivity variable and then use its reference to call/execute GridView's methods (like "resetGrid()").
ResetButton lives OUTSIDE GridView so it's a bad pratice to reference "resetButton" from INSIDE GridView extended class.
Pseudo code:
class GridView extends View {
public void resetGrid() {
...do reset stuff here...
}
}
class MainActivity extends Activity {
private GridView mGridView;
private Button mResetButton;
public onCreateView() {
...
mGridView = findViewById(R.id.gridview);
mResetButton = findViewById(R.id.resetButton);
resetButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mGridView.resetGrid();
}
});
}
}

RecyclerView Onclick (call non-static method)

I've got stuck with an issue about setting an OnItemClickListener to my RecyclerView items. I tried to set a listener the way described in the RecyclerView sample of Android Studio. So a listener is set in the ViewHolder class for my RecyclerView.
public class ProgramViewHolder extends RecyclerView.ViewHolder {
protected TextView vName;
protected ImageView vProgramImage;
public ProgramViewHolder(View v) {
super(v);
vName = (TextView) v.findViewById(R.id.programName);
vProgramImage = (ImageView) v.findViewById(R.id.programImage);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// HERE PROBLEM !!
MainActivity.openSettings(1);
}
});
}
}
Now I want to call a method of my MainActivity openSettings(int ) to load a fragment:
public void openSettings(int layoutId) {
settingsFragment setFrag = new settingsFragment();
Bundle information = new Bundle();
information.putInt("layoutId", layoutId);
setFrag.setArguments(information);
getFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, setFrag)
.commit();
}
But now the problem. When I try to compile, it says "Non-static method 'openSettings(int )' cannot be referenced from a static context."
I quite not understand this error. Why is it a static context? The class ProgramViewHolder ist not declared static.
And the most important part: How can I fix it? I want to set a OnClickListener to every item of RecyclerView and call a public method of MainActivity.
Thanks a lot to you, for your time spending to help me.
It's not that ProgramViewHolder is static, it's because attempting to call your activity from a static context (you aren't calling a specific instance of the activity).
What you should do is pass the activity into your recyclerViewAdapter so that you have access to it.
For example
MainActivity mainActivity;
public CustomRecyclerViewAdapter(MainActivity mainActivity) {
this.mainActivity = mainActivity;
}
And to create the recyclerViewAdapter from MainActivity
CustomRecyclerView recyclerViewAdapter = new CustomRecyclerViewAdapter(this);
recyclerViewAdapter.setAdapter(recyclerViewAdapter);
You should then be able to access your method like this
mainActivity.openSettings(1);
Let me know if you have any trouble
//Edit
Here's how you would set onClick from bindViewHolder. You want to set up any onClickListeners here due to the way RecyclerView "recycles" data. For example, if each row should perform a different action on click, you need to make sure the click listener is tied to the specific row. Creating this in onBindViewHolder ensures this. If you want an entire row to be clickable, rather than elements inside, just create an outer view that fills the entire row. Then tie the onClickListener to that.
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
ProgramViewHolder programViewHolder = (ProgramViewHolder) holder;
programViewHolder.vName.setOnClicklistener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mainActivity.openSettings(1);
}
});
}
if you have context of the activity containing recyclerView, then you can simply do this:
your_view_holder.v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// HERE SOLUTION!!
((MainActivity)context).openSettings(1);
}
});
You can place this in onBindViewHolder(...)
How to get context:
Create another parameter of context in your Adapter's constructor , and pass the context from your activity once instantiating Adapter .
why pass the context:
i would recommend you to always pass context and assign it to any adapter's variable because this is something you would require every now and then while working with your adapter, so instead of using a workaround every time for context, just save it once .

Extending a second GameView in Android

I'm making an application on Android which is to contain 2 games. I've done this but I've come across a problem that the two buttons that are supposed to extend to different GameViews are extending to the same GameViews. The classes both have different names and I've tried changing some of the content to specifically refer to the BallGameView class however it causes the program not to compile. I've had a look around to see if there's anything on extending to 2 separate GameViews in a single application but not came across anything so far.
EDIT: For clarity, the problem is that the buttons that should open different games are opening the same game. The game is compiling but not as I want it to. I'll post the code that's referring to the different games below.
public class BallGameActivity extends Activity {
GameView GV;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ballgame);
GV = new GameView(this);
setContentView(GV);
To refer to Ball Game.
public class BallSplash extends Activity implements View.OnClickListener {
Button playBallButton;
Button guideButton;
Intent ballIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ball_splash);
playBallButton = (Button)findViewById(R.id.startBallGame);
guideButton = (Button)findViewById(R.id.guideButton);
playBallButton.setOnClickListener(this);
guideButton.setOnClickListener(this);
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.startBallGame:
ballIntent = new Intent(this,BallGameActivity.class);
startActivity(ballIntent);
break;
case R.id.guideButton:
ballIntent = new Intent(this,Guide.class);
startActivity(ballIntent);
break;
}
}
To refer to Sprite Game
public class Splash extends Activity implements View.OnClickListener {
Button playButton;
Button instructionButton;
Intent intent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
playButton = (Button)findViewById(R.id.toPlay);
instructionButton = (Button)findViewById(R.id.toInstructions);
playButton.setOnClickListener(this);
instructionButton.setOnClickListener(this);
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.toPlay:
intent = new Intent(this,GameActivity.class);
startActivity(intent);
break;
case R.id.toInstructions:
intent = new Intent(this,InstructionActivity.class);
startActivity(intent);
break;
}
}
Maybe the problem exists because you call setContentView() twice. You should remove the wrong one.
The correct way to do it is to call that class that you want to use as the view
BallGameView GV = new BallGameView(this);
setContentView(GV);
in your current code you are instantiating GameView but that isn't what you want for this Activity. You need to instantiate BallGameView GV instead. Since you are using
GV = new GameView(this);
setContentView();
in both Activities, you are seeing the same thing no matter which Activity you start. So the problem was never with starting an activity or extending anything.
Also, you can remove
setContentView(R.layout.activity_ballgame);
That line will set the Activity to use that layout. But since you are calling setContentView() again and using the class which extends SurfaceView then it will set the Activity to use that as the layout instead, making the above line useless.

The different OnClickListener implementation ways

What is the difference between:
public class MainActivity extends Activity {
public void onCreate (Bundle savedInstanceState) {
button1 = (Button) findViewById(R.id.btn1);
button1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// Click code
}
)};
}
}
And:
public class MainActivity extends Activity implements OnClickListener {
public void onCreate (Bundle savedInstanceState) {
button1 = (Button) findViewById(R.id.btn1);
button1.setOnClickListener(this);
}
public void onClick(View arg0) {
switch(arg0.getId()) {
case R.id.button1:
// Click code
break;
}
}
}
They have both the exact same functionality and results.
The first method uses an anonymous inner class that implements the interface method. By using this approach, you receive events only for that particular View.
In the second method, you entire Activity class implements the OnClickListener interface. You can set the OnClickListener of every View to this, and receive all the click events in one method, where you can then filter them and act upon them.
The first method translates to:
Button.OnClickListener anonymous_listener = new Button.OnClickListener() { ... };
button.setOnClickListener(anonymous_listener);
Which is to say that it dynamically creates and stores a new OnClickListener instance when you use it.
In the second method, your entire class uses one single instance of the OnClickListener, that is passed to all the Views you want to listen for clicks on.

How to attach this listener in an activity

I was wondering how do i attach this(OnGenericMotionListener) listener inside an activity. Do i have to register it to each view? thanks
note: please provide code.
To add any interface to a class in java you just need to add the word implements and then the class name to the top of the activity declaration. So to add the OnGenericMotionListener you would use the code below.
public class MyActivity extends Activity implements OnGenericMotionListener {
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
TextView myView = new TextView(this);
myView.setOnGenericMotionListener(this);
}
#Override
public boolean onGenericMotion(View view, MotionEvent event) {
return false;
}
}
This would set the GenericMotionListener for myView so when the event occurs it will call the onGenericMotion function inside of your activity. If you want to attach it to multiple views just use a switch on the id of the view passed to the onGenericMotion function.

Categories