I have an abstract Activity called Animal and two concrete descendant Activities Cat and Dog.
Cat & Dog are to present the same UI, consisting of a single button and so there is a single layout, activity_animal.xml that Animal sets as it's content view in OnCreate.
I want to set the button's OnClickListener in the abstract Animal class by means of an anonymous implementation of OnClickListener
private void setClickHandlers() {
((Button) findViewById(R.id.btn))
.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
//how to get a reference to this?
}
});
}
and in onClick I want to make a new Intent. To make the Intent I need a reference to this.
Normally, in anonymous method code like this, I could use syntax such as
EnclosingClass.this
but here, I don't know what the enclosing class will be. At run time, it could be either a Cat or a Dog.
How to do this?
The only way I can think of is to provide an abstract getThis() in Animal which is overridden in each concrete descendant.
You should be able to say Animal.this as your context.
private void setClickHandlers() {
View view = findViewById(R.id.btn);
view.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
Intent intent = new Intent(Animal.this, MyDestinationActivity.class);
...
}
});
}
Animal.this will be either a Cat or Dog but since you only need Context the distinction is irrelevant.
public void onClick(View arg0) {
Activity host = (Activity) arg0.getContext();
}
I'd do it like:
private void setClickHandlers() {
final Animal thiz = this;
((Button) findViewById(R.id.btn))
.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
Intent intent = new Intent( thiz, AAAA.class );
}
});
}
You can determine the runtime type by using the instanceof operator.
if (Animal.this instanceof Dog) {
// dog related
}
else {
// cat related
}
Related
I saw some different ways of implementing onItemClickListener for RecyclerView. My favourite is to use interface callback:
Interface:
public interface OnClickListener {
void onCardClick(View v);
void onFavouriteButtonClick(View v);
void onRemoveClick(View v);
//Other clickable areas
}
In adapter:
currentView.favouriteButton.setTag(currentItem.getId());
currentView.favouriteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (OnClickListener != null){
OnClickListener.onFavouriteButtonClick(v);
}
}
});
In main activity/fragment
adapter = new CardAdapter( .... new OnClickListener() {
#Override
public void onFavouriteButtonClick(View v) {
int id = Integer.parse(v.getTag().toString());
//Do your stuff
}
....
});
So, I have some questions:
is it good way of handling things?
will performance be slow if number of items will grow?
any reasons why I shouldn't use this approach?
I think you could improve upon this by not passing the view outside of the adapter.
// Create an object that encapulates the information for each card
public class CardInfo {
// Whatever you want to show in your card
}
// Create a listener for items instead of views
public interface OnCardAction {
void onCardSelected(CardInfo cardInfo);
void onFavoriteSelected(CardInfo cardInfo);
void onCardRemoved(CardInfo cardInfo);
}
// In your adapter
favoriteButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
// You many need to check if onCardActionLisetner is null
CardInfo cardInfo = getItemAt(viewHolder.getAdapterPosition());
onCardActionListener.onFavoriteSelected(cardInfo);
}
});
NOTE: If you are passing the listener in the constructor can either make it required (throw error if it is null) or not even create View.OnClickListner to reduce the number of null checks.
Is it wrong to do that or will it work just fine? I'm trying to make every relative layout clickable and when you click on it it takes you to a new page where the mGameTitle and mReleaseDate are passed to this new activity.
I'm doubting if it will work 'cause I'm getting an error with View.OnClickListener; must either be declared abstract or implement abstract method 'onClick(View)' in 'OnClickListener
public void onBindViewHolder(final ViewHolderUpcoming viewHolderUpcoming, int i) {
Game currentGame = listOfGames.get(i);
viewHolderUpcoming.mReleaseDate.setText(currentGame.getReleaseDate());
viewHolderUpcoming.mGameTitle.setText(currentGame.getTitle());
viewHolderUpcoming.mLayout.setOnClickListener(new View.OnClickListener() {
//Intent intent = new Intent(this, GamePage.class);
});
}
As the error states, you need to implement onClick(View).
viewHolderUpcoming.mLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Context context = v.getContext();
//TODO: Implementation
}
});
I know there are similar questions asked before in SO, but sorry to say that, none of them are serving my purpose.
I have a button in an activity class, and I want to give its functionality in another class.
Below is my HomeActivity code:
// Tile Button
tileButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
TileButton tileView = new TileButton();
tileView.tile();
}
});
And here is TileButton.java class code:
public class TileButton {
HomeActivity homeActivity = new HomeActivity();
View view = homeActivity.hometabView;
public void tile(){
if(view.isShown()){
view.setVisibility(View.INVISIBLE);
}else{
view.setVisibility(View.VISIBLE);
}
}
}
Now when I press the tile button, a Null Pointer Exception is thrown. Below is the LogCat entry.
10-04 10:32:07.833: E/AndroidRuntime(5330): java.lang.NullPointerException
How do I solve this problem? Please help
Change:
public class TileButton {
public void tile(View view){
if(view.isShown()){
view.setVisibility(View.INVISIBLE);
}else{
view.setVisibility(View.VISIBLE);
}
}
}
// Tile Button
tileButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
TileButton tileView = new TileButton();
tileView.tile(v);// you can pass any view from here
}
});
If you want to have same operation in both the activities, Create a public method in one of the activity and just call the method onClick of both buttons. But you cannot control the visibility of an activity which is not even on screen.
I'm new to android and Java. I want to make an onClick method which carries an int argument, so this is my attempt:
public void randomClick(final int randomIndex)
{
private OnClickListener top_listener = new OnClickListener() {
public void onClick(View v) {
Intent top = new Intent(Main.this, ProjectDetail.class);
top.putExtra("spendino.de.ProjectDetail.position", randomIndex);
startActivity(top);
}
};
}
but it still contains error, can anybody fix that for me?
Later I want set the method to an ImageView, it will look more or less like this image1.randomClick(randomIndex1);.
Currently in your implementation the OnClickListener is not bounded to any view, so it won't get fired.
You should create your own (might be inner but not anonymous) class implementing the OnClickListener interface:
public class RandomClickListener implements View.OnClickListener
{
private final int randomIndex;
public RandomClickListener(final int randomIndex)
{
this.randomIndex = randomIndex;
}
#Override
public void onClick(View v)
{
Intent top = new Intent(Main.this, ProjectDetail.class);
top.putExtra("spendino.de.ProjectDetail.position", randomIndex);
startActivity(top);
}
}
[...]
image1.setOnClickListener(new RandomClickListener(randomIndex));
This way when you click on the image1 it will start the ProjectDetail activity with the randomIndex set above.
If you'd like to explicitly start the ProjectDetails activity (without any user interactions such as a click), you don't need an OnClickListener at all.
I am trying to run a test program that allows a user to click a button and move to a different screen. I have the Home(First Activity) and Away(Second Activity) classes and a xml file specifying the layout for each. My source code is as follows:
public class Home extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button create = (Button)findViewById(R.id.create);
create.setOnClickListener(new View.OnClickListener() {
public void onClick(View v)
{
Intent intent = new Intent(Home.this, Away.class);
startActivity(intent);
}
});
setContentView(R.layout.main);
}
}
And Away.java
public class Away extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.away);
}
}
I get a NullPointerException in the DDMS trace
at Home.onCreate(line 17)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java: 2627)
Anyone see anything in my code that may be causing this?
findViewById() traverses the view hierarchy set up when setContentView() inflates your layout. You cannot retrieve a reference to a view in your XML before you have called setContentView(). Change your onCreate() method in Home to look like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Call me first
setContentView(R.layout.main);
Button create = (Button)findViewById(R.id.create);
create.setOnClickListener(new View.OnClickListener() {
public void onClick(View v)
{
Intent intent = new Intent(Home.this, Away.class);
startActivity(intent);
}
});
}
Otherwise, findViewById() will return null because there are no views in the tree...thus, a view with your requested id value doesn't exist.
Hope that helps!
If the findViewById call can't find the actual thing you are looking for, it could return a null object and cause the call to setOnClickListener to throw an NPE. Are you sure you've got the right ID (R.id.create) specified?