I implemented a bottom button bar(something like a tab bar controller in iPhone). For this I created a common layout (button_bar.xml, 5 image buttons) and included in other activity xml files. and for the managing the click action I created a BaseActivity.java extended from Activity and perform the click actions. and I extend other activity which need button bar from this BaseActivity, which works fine. Now I want to include a selected state to these buttons, but when I access the buttons in base activity it give a null pointer error. How can I solve this.
button_bar.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/bottomButtonBar"
style="#android:style/ButtonBar"
... >
<ImageButton
android:id="#+id/btnGuests"
android:onClick="showAllGuests"
android:src="#drawable/ic_guest_list" />
<ImageButton
android:id="#+id/btnAddGuest"
android:onClick="selectGuestType"
android:src="#drawable/ic_add_guest" />
<ImageButton
android:id="#+id/btnAddParty"
android:onClick="showAddParty"
android:src="#drawable/ic_add_party" />
....
</LinearLayout>
public class BaseActivity extends Activity {
// common to other activities.
public void showAddParty(View view) {
//showAddParty is one one of the buttons click method. 4 more buttons are there
Intent intent = new Intent(this, AddPartyActivity.class);
startActivity(intent);
// I can get "view.findViewById(R.id.btnAddParty)" here
// but I can't get "findViewById(R.id.btnAddGuest)" here. how this possible
}
}
public class AddPartyActivity extends BaseActivity{
....
}
Here i can get the corresponding view from parameter view, and change backgroundIbageSource. but when it goes to "AddPartyActivity" that inherited from Baseactivity, the new image is replaced by old one. How can I implement the selected feature in BaseActivity itself?
you can hold the state of the Button(clicked or not) using booloean in BaseActivity and check the value of these variables in AddPropertyActivity's onCreate() method.
public class BaseActivity extends Activity {
protected static boolean isButton1Clicked = false;
protected static boolean isButton2Clicked = false;
protected static boolean isButton3Clicked = false;
protected static boolean isButton4Clicked = false;
.....
public void showAddParty(View view) {
isButton1Clicked = true;
//showAddParty is one one of the buttons click method. 4 more buttons are there
Intent intent = new Intent(this, AddPartyActivity.class);
startActivity(intent);
}
}
public class AddPartyActivity extends BaseActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
Button button1 = (Button)findViewById(R.id.button1);
if(isButton1Clicked) {
button1.setBackground(R.drawable.clicked);
} else {
button1.setBackground(R.drawable.not_clicked);
}
......
......
}
}
and remember that all boolean variables must be static variables. (every object will have it's own copy of instance variables but all objects will share a single copy of static members).
public class BaseActivity extends Activity {
protected static boolean isButton1Clicked = false;
protected static boolean isButton2Clicked = false;
protected static boolean isButton3Clicked = false;
protected static boolean isButton4Clicked = false;
protected Button button1;
protected Button button2;
protected Button button3;
protected Button button4;
protected void checkButtonsState() {
if (isButton1Clicked) {
button1.setBackgroundResource(R.drawable.image1);
} else {
button1.setBackgroundResource(R.drawable.image2);
}
..........
}
public void showAddParty(View view) {
isButton1Clicked = true;
// showAddParty is one one of the buttons click method. 4 more
// buttons are there
Intent intent = new Intent(this, AddPartyActivity.class);
startActivity(intent);
}
}
public class AddPartyActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1 = (Button) findViewById(R.id.button);
button2 = (Button) findViewById(R.id.item1);
.....
checkButtonsState();
}
}
Your error come from because you are using view.findViewById(), but the view variable correspond of the object that catch the click event (look in your xml, the 'android:onClick="showAddParty"').
So, you have in parameter a view instance that point directly to the btnAddParty button.
Is why you can access with findViewById to btnAddParty id but not btnAddGuest id.
You can access to all the view hierarchy by using direct findViewById as method of the activity class:
View btAddParty = findViewById(R.id.btnAddParty)
View btAddGuest = view.findViewById(R.id.btnAddGuest)
Now, you can have a full solution, by implement a special method (setMyInternalContent in the sample below) in the BaseActivity and keep an instance of each button, after, you just have to update there state on click action:
public class BaseActivity extends Activity {
protected Button mBtAddParty;
protected Button mBtAddGuest;
// ...
protected void setMyContentView(int resId) {
setContentView(resId);
mBtAddParty = (Button)findViewById(R.id.btnAddParty);
mBtAddParty = (Button)findViewById(R.id.btnAddGuest);
// ...
}
public void showAddParty(View view) {
mBtAddParty.setClickable(true);
mBtAddGuest.setClickable(false);
// ...
//showAddParty is one one of the buttons click method. 4 more buttons are there
Intent intent = new Intent(this, AddPartyActivity.class);
startActivity(intent);
}
}
public class AddPartyActivity extends BaseActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setMyContentView(R.layout.activity_layout);
// Do not forget to set initial button state:
mBtAddParty.setClickable(true);
mBtAddGuest.setClickable(false);
// ...
}
}
Related
I just started to learn Java. I know some C++, but you know, I am just a novice. I have a problem with a button. I a main activity there are 3 buttons with onClick discovered by switch. By clicking on one of the buttons you're redirected to another activity where I need to create a new button.
The code responsible for MainScreen buttons looks like this (and it works):
public class MainScreen extends Activity implements View.OnClickListener {
Button act_2x2, act_3x3, act_4x4;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
act_2x2 = (Button) findViewById(R.id.Activity_2x2);
act_3x3 = (Button) findViewById(R.id.Activity_3x3);
act_4x4 = (Button) findViewById(R.id.Activity_4x4);
act_2x2.setOnClickListener(this);
act_3x3.setOnClickListener(this);
act_4x4.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch(view.getId())
{
case R.id.Activity_2x2:
Intent inent1 = new Intent(this, macierz_2x2.class);
startActivity(inent1);
break;
case R.id.Activity_3x3:
Intent inent2 = new Intent(this, macierz_3x3.class);
startActivity(inent2);
break;
case R.id.Activity_4x4:
Intent inent3 = new Intent(this, macierz_4x4.class);
startActivity(inent3);
break;
}
And it is okay, I can normally enter the new activity, for example Activity_2x2.
Here, in 2x2 class I've created a new OnClickListener and when I click on it, nothing happens. I am sitting here for two hours with debugger, it is saying that I don't have permissions, but It is impossible, because it is just a simple button. I am using Android Studio and just don't know how to debug correctly.
Here is the definition:
public class macierz_2x2 extends MainScreen implements View.OnClickListener{
Button b_2x2;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_2x2);
b_2x2 = (Button) findViewById(R.id.button_2x2);
b_2x2.setOnClickListener(this);
}
public void OnClick(View view) {
what happens after clicking
}
I know, that this problem is somewhere in overriding and extending, but no idea, why the compiller is letting this being compiled.
If someone have any idea, I will be grateful.
ps. I don't need an answer, just a point, what is wrong.
public class macierz_2x2 extends MainScreen implements View.OnClickListener{
MainScreen already implements View.OnClickListener. Remove it from the definition of your class.
public class macierz_2x2 extends MainScreen {
is enough. You can override onClick on your macierz_2x2 activity
#Override
public void onClick(View view) {
switch(view.getId()) {
R.id.button_2x2:
// do something
break;
default:
super.onClick(view);
break;
}
}
I have the following code:
public class SplashScreenActivity extends Activity {
private boolean animated ;
private Handler handler1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!isPreviouslyLoggedIn()) {
setContentView(R.layout.splash);
final TextView revolution=(TextView) findViewById(R.id.textView1);
final Button login=(Button) findViewById(R.id.loginButton);
final Button signUp=(Button) findViewById(R.id.signUpButton);
login.setOnClickListener(loginListener);
signUp.setOnClickListener(signUpListener);
if (!animated) {
animated = true;
revolution.setVisibility(View.INVISIBLE);
login.setVisibility(View.INVISIBLE);
signUp.setVisibility(View.INVISIBLE);
ImageView image = (ImageView) findViewById(R.id.image);
TranslateAnimation slide = new TranslateAnimation(0, 0, 100, 0);
slide.setDuration(1000);
image.startAnimation(slide);
handler1 = new Handler();
handler1.postDelayed(new Runnable() {
#Override
public void run() {
revolution.setVisibility(View.VISIBLE);
login.setVisibility(View.VISIBLE);
signUp.setVisibility(View.VISIBLE);
}
},1200);
}
}
else {
setContentView(R.layout.home);
Intent intent = new Intent(getApplicationContext(), PickUpActivity.class);
startActivity(intent);
}
}
When the user clicks on one of the buttons, it leads him to a different activity in the same app. However, when the user clicks back from the next activity, the animation is started again. How can I prevent the animation from showing again as i want it to occur only once when user opens the app?
You can use Application class.Declare a boolean var in it and set it "true" before starting second Activity.In your onCreate() of first Activity check this boolean and do animation only it is false(it means that user has not started second activity yet).For example create class with name App in your package:
public class App extends Application{
private static boolean animated;
#Override
public void onCreate() {
super.onCreate();
animated = false;
}
public static boolean getAnimated(){
return animated;
}
public static void setAnimated(boolean animated1){
animated = animated1;
}
}
Register App in manifest:
<application
android:icon= ...
android:label= ...
android:name="yourpackage.name.App" >
(I suppose that your package name is :"yourpackage.name")
Now change your code like this:
if (!App.getAnimated()) {
App.setAnimated(true);
revolution.setVisibility(View.INVISIBLE);
login.setVisibility(View.INVISIBLE);
signUp.setVisibility(View.INVISIBLE);
...
Or you can use sharedpreferences and retrieve a boolean from it when you want to start animation.You have to set it's default value "false" and when user start second Activity,you have to set it "true".
You can set a flag for this, first time keep the flag true and when the user clicks on any of the button, set the flag value to false.
Now start the animation if the flag value is true.
I want write code once and use in different activities. I have created a Base Activity class for that . Also the header of all the layouts in different activities are same. I have done that with the help of the <include layout > tag.
Now the Problem is my BaseActivity code is not running. I am trying this first time se don't have much idea about that.
1.)The BaseActivity code is below :
package com.waheguru.app;
import android.R.integer;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public abstract class BaseActivityMenu extends Activity {
//action id
private static final int ID_UP = 1;
private static final int ID_DOWN = 2;
private static final int ID_SEARCH = 3;
private static final int ID_INFO = 4;
private static final int ID_ERASE = 5;
private static final int ID_OK = 6;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.header);
ActionItem nextItem = new ActionItem(ID_DOWN, "Book", getResources().getDrawable(R.drawable.menu_down_arrow));
ActionItem prevItem = new ActionItem(ID_UP, "Bookmark", getResources().getDrawable(R.drawable.menu_up_arrow));
ActionItem searchItem = new ActionItem(ID_SEARCH, "Find", getResources().getDrawable(R.drawable.menu_search));
ActionItem infoItem = new ActionItem(ID_INFO, "Info", getResources().getDrawable(R.drawable.menu_info));
ActionItem eraseItem = new ActionItem(ID_ERASE, "Clear", getResources().getDrawable(R.drawable.menu_eraser));
ActionItem okItem = new ActionItem(ID_OK, "OK", getResources().getDrawable(R.drawable.menu_ok));
//use setSticky(true) to disable QuickAction dialog being dismissed after an item is clicked
prevItem.setSticky(true);
nextItem.setSticky(true);
//create QuickAction. Use QuickAction.VERTICAL or QuickAction.HORIZONTAL param to define layout
//orientation
final QuickAction quickAction = new QuickAction(this, QuickAction.VERTICAL);
//add action items into QuickAction
quickAction.addActionItem(nextItem);
quickAction.addActionItem(prevItem);
quickAction.addActionItem(searchItem);
quickAction.addActionItem(infoItem);
quickAction.addActionItem(eraseItem);
quickAction.addActionItem(okItem);
//Set listener for action item clicked
quickAction.setOnActionItemClickListener(new QuickAction.OnActionItemClickListener() {
public void onItemClick(QuickAction source, int pos, int actionId) {
ActionItem actionItem = quickAction.getActionItem(pos);
//here we can filter which action item was clicked with pos or actionId parameter
if (actionId == ID_SEARCH) {
Toast.makeText(getApplicationContext(), "Let's do some search action", Toast.LENGTH_SHORT).show();
} else if (actionId == ID_INFO) {
Toast.makeText(getApplicationContext(), "I have no info this time", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), actionItem.getTitle() + " selected", Toast.LENGTH_SHORT).show();
}
}
});
//set listnener for on dismiss event, this listener will be called only if QuickAction dialog was dismissed
//by clicking the area outside the dialog.
quickAction.setOnDismissListener(new QuickAction.OnDismissListener() {
public void onDismiss() {
Toast.makeText(getApplicationContext(), "Dismissed", Toast.LENGTH_SHORT).show();
}
});
Button books=(Button)findViewById(R.id.book);
books.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent intent=new Intent(ExampleActivity.this,List_of_books.class);
startActivityForResult(intent, 0);
}
});
//show on btn1
Button btn1 = (Button) this.findViewById(R.id.menu);
btn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
quickAction.show(v);
}
});
}
}
2.) The Activity extended the Base Activity
package com.waheguru.app;
import android.app.Activity;
import android.os.Bundle;
public class ABCActivity extends BaseActivityMenu {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home);
}
}
So can any one help me where I am doing something wrong.
For this you have to create one header.xml which will be included in each and every layout for your activities as follows
header.xml
<RelativeLayout>
<TextView android:id="#+id/txtHeading"
.... />
</RelativeLayout>
activity_main.xml
<RelativeLayout>
<!-- include your header here -->
<include layout="#layout/header"
... />
<!-- Rest of your views -->
</RelativeLayout>
BaseActivity
abstract class BaseActivity extends Activity {
protected TextView txtHeading;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
protected void setHeading(int resId) {
if(txtHeading == null)
txtHeading = findViewById(R.id.txtHeading);
if(txtHeading != null)
txtHeading.setText(resId);
}
}
MainActivity
class MainActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setHeading(R.string.heading_main);
}
}
You can put as many views you want and manage common things in BaseActivity or BaseListActivity.
If you are making inheritance with activities and your base activity calls setContentView and after that the real activity calls setContentView the last call will set the layout for activity. So if you are looking for a solution where all activies have the same header component the are 2 ways.
For each activity layout xml you include that component
-You make function for baseActivity e.g. setContent(int layout_id)
-You call that with your activity always.
-Baseactivity inflates a root view with header and inflates layout_id view to that layout.
-Then calls the actual setContentView with that component.
I think you should achieve it using Fragment, this may helps you.
1 - in main.xml, add:
<fragment
android:id="#+id/header"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
class="com.package.name.HeaderPanel" />
//remaining is same
2 - the BaseActivity which extends FragmentActivity:
public class BaseActivityMenu extends FragmentActivity {
private static final String TAG = Default.class.getName() + " - ";
private int mResLayoutId;
public void onCreate(Bundle savedInstanceState, int resLayout){
super.onCreate(savedInstanceState);
setContentView(resLayout);
mResLayoutId = resLayout;
switch(mResLayoutId){
// here change with your xml file
case R.layout.home:
// set here common control like header textview
break;
default:
break;
}
}
}
3 - Now, you can extend your Activity with the BaseActivity. This will allow the Activity to be extended by FragmentActivity:
public class ABCActivity extends BaseActivityMenu {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState, R.layout.home);
}
}
In code, your base activity is called ExampleActivity, but in your child class you are extending BaseActivityMenu. Don't know where its coming from.
Perhaps change:
public class ABCActivity extends BaseActivityMenu
To this:
public class ABCActivity extends ExampleActivity
Moreover, I would suggest you to define your base activity (ExampleActivity) as an Abstract class.
For example:
public abstract class ExampleActivity extends Activity
Doing so will not define your base class as concrete and will make it easier to debug in case of problems.
I'm new in Android development and I wanted to make application that has header, body and footer and by clicking on one of the buttons in footer some layout will be loaded into body. I used some kind of "MasterPage" as described here.
When the button is pressed neither new_exercise layout nor exercises layout is loaded. Why? Maybe instead of all of this I should use any kind of tabs? Or maybe I can't inflate layout and should create new activity?
Here the code of the BaseActivity and NewExercise activity:
public class BaseActivity extends Activity{
LinearLayout linBaseBody;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.base_layout);
linBaseBody = (LinearLayout)findViewById(R.id.base_body);
initButtons();
}
#Override
public void setContentView(int id) {
LayoutInflater inflater = (LayoutInflater)getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(id, linBaseBody);
}
private void initButtons()
{
Button btn1 = (Button) findViewById(R.id.newEx);
btn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
setContentView(R.layout.new_exercise);
}
});
Button btn2 = (Button) findViewById(R.id.showAllEx);
btn2.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
setContentView(R.layout.exercises);
}
});
}
public class NewExercise extends BaseActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.new_exercise);
}
}
public class Exercises extends BaseActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.exercises);
}
}
How your code is written, it would make more sense to use a new Activity. However, If you wanted to keep all of the view in one Activity, you could walk through all of your layouts calling mLayout.setVisible(View.VISIBLE); or you could use ViewStubs.
As to answer your question, why, what you are doing is adding the view (and their layouts) directly to your already created and inflated content view (the one you created in onCreate). You will need to clear the Activities contentView first to see the changes you are making with the button.
I created a custom dialog that extends Dialog. One button on that the dialog is an “OK” button which the user is expected to press when finished entering information in other fields. I cannot get any listeners set to that button to fire.
public class HeightDialog extends Dialog {
private Button okButton;
…
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.heightdialog);
this.okButton = (Button)this.findViewById(R.id.userOkWithHeight);
this.okButton.setOnClickListener(new android.view.View.OnClickListener() {
public void onClick(View v) {
// Does not fire
HeightDialog.this.dismiss();
return;
}
});
this.okButton.setOnLongClickListener(new OnLongClickListener() {
public boolean onLongClick(View v) {
// Does not fire
HeightDialog.this.dismiss();
return true;
}
});
this.okButton.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// Does not fire
HeightDialog.this.dismiss();
return true;
}
});
…
}
I also attempted an implementation where the Dialog class implemented the listeners(http://www.androidcompetencycenter.com/2009/01/android-basics-dialogs-and-floating-activities/) instead of using inner classes(http://about-android.blogspot.com/2010/02/create-custom-dialog.html):
Still no luck.
public class HeightDialog extends Dialog implements View.OnClickListener {
private Button okButton;
…
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.heightdialog);
this.okButton = (Button)this.findViewById(R.id.userOkWithHeight);
this.okButton.setOnClickListener(this);
public void onClick(View view){
HeightDialog.this.dismiss();
return;
}
…
}
I have set breakpoints inside each of the listeners in both versions of the implementation, and the debugger never stops execution. I have attempted to use inner classes for the listeners which did not solve the problem.
Any clues?
Thanks
I found a solution here:
Handling buttons in custom dialogs
It works in my case.
dialog = new Dialog(this);
dialog.setContentView(R.layout.custom_dialog);
dialog.setTitle("Custom Dialog");
Button dialog_btn = (Button) dialog.findViewById(R.id.dialog_button);
dialog_btn.setOnClickListener(new View.OnClickListener()
{
// Perform button logic
}
Why I am not sure why following the two examples mentioned in my post did not work, I figured out how to get it to work. I had to move the attachment of my listener to the button in the dialog's onStart() method from the dialog's onCreate() method.
It appear this is related to me also overriding the onStart() method in my custom dialog:
public void onStart() {
super.onStart();
setContentView(R.layout.heightdialog);
...
}
That code must have "zeroed" out my listeners which were in the onCreate() method.
In order to intercept button clicks HeightDialog must implement View.OnClickListener
public class HeightDialog extends Dialog implements View.OnClickListener
{
}