This is a simpler version of something I'm working on. When the add button is pressed, what is supposed to happen is, a LinearLayout is created and a CheckBox is also created with the text within the EditText box. The CheckBox is then placed into the newly created LinearLayout, and the newly created LinearLayout, placed in the already existing LinearLayout(named layout). I know it seems unnecessary to create a new LinearLayout but in the main program, its really important. My problem is, when I run the code, the app 'force closes' so I want to know what it is that I'm doing wrong or if there is a better approach I can take to achieve the result I need.
package co.cc.*******.toDo;
import co.cc.*******.R;
import android.app.Activity;
import android.os.Bundle;
import android.view.*;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
public class ToDoMainActivity extends Activity implements View.OnClickListener{
/** Called when the activity is first created. */
Button bAdd,bremove;
EditText et;
// CheckBox cbNew;
LinearLayout layout;//main layout
ArrayList<CheckBox> cbNew;//dynamic array of checkBoxes
ArrayList<LinearLayout> cbLayout;//dynamic array of LinearLayouts
int index = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initialize();
bAdd.setOnClickListener(this);
bremove.setOnClickListener(this);
}//end method onCreate
void initialize(){
bAdd = (Button)findViewById(R.id.bAdd);
bremove = (Button)findViewById(R.id.bremove);
et = (EditText)findViewById(R.id.et);
layout = (LinearLayout)findViewById(R.id.layout);
cbNew = new ArrayList<CheckBox>();
}//end method initialize
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId())
{
case R.id.bAdd:
cbLayout.add(index, new LinearLayout(this));//create new layout to store cb
cbNew.add(index, new CheckBox(this));//create new checkbox
cbNew.get(index).setText(et.getText().toString()+ index);//set text to text in editText box
cbLayout.get(index).addView(cbNew.get(index));//add checkbox to newly created layout
layout.addView(cbLayout.get(index));//add newly created layout to already existing layout
index ++;
break;
}//end switch
//layout.removeView(cbNew.get(index));
}//end method onClick
}//end class ToDoMainActivity
Related
I have got a little problem which is for me impossible to solve. I've got lots of TableRows called Radek_X and they are set to be android:visibility="gone".
And I need that if you for the first time, click on button(there is only one button for that process) it will change Radek_1 to android:visibility="visible" if you click on the button for the second time it will change Radek_2 from gone to visible, while Radek_1 is still visible. And so on for all others TableRows. I'm really desperate. I will be very grateful for any help! Have a nice day!
Here is my java file
package jansoldat.formular100;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.TableRow;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
Button buttonPridejStaniceni;
TableRow Radek_2, Radek_3, Radek_4,Radek_5,Radek_6;
#Override
private ArrayList<String> arrayList;
private ArrayAdapter<String> adapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonPridejStaniceni = (Button) findViewById(R.id.buttonPridejStaniceni);
Radek_2 = (TableRow) findViewById(R.id.Radek_2);
Radek_3 = (TableRow) findViewById(R.id.Radek_3);
Radek_4 = (TableRow) findViewById(R.id.Radek_4);
Radek_5 = (TableRow) findViewById(R.id.Radek_5);
Radek_6 = (TableRow) findViewById(R.id.Radek_6);
}
public void PridejDalsiStaniceniClicked(View v)
{
Radek_2.setVisibility(View.VISIBLE);
Radek_3.setVisibility(View.VISIBLE);
Radek_3.setVisibility(View.VISIBLE);
Radek_4.setVisibility(View.VISIBLE);
Radek_5.setVisibility(View.VISIBLE);
Radek_6.setVisibility(View.VISIBLE);
}
}
`
It's actually easier than you think, change your onClick method, which I assume you're setting by xml to PridejDalsiStaniceniClicked to this:
int[] views = new int[]{R.id.Radek_2,R.id.Radek_3,R.id.Radek_4};//...
int counter = 0;
public void PridejDalsiStaniceniClicked(View v)
{
findViewById(views[counter]).setVisibility(View.VISIBLE);
if(counter<views.length){
counter++;
}
}
What happens inside is that we will fetch the view that matches the counter of times pressed while there are still views in the array. Some people don't realize that view ids are integers and can be stored in an array like in the example.
I'm programming an Android calculator in Eclipse. I want to be able to set up the OnClickListener for several variables instead of having to code a listener for each one. Seems like overkill. Is there a way to do this using an array, maybe? Much help would be appreciated.
package rechee.cool;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class HelloAndroidActivity extends Activity {
/** Called when the activity is first created. */
int counter=0;
//Just have two buttons so far, I'm going to have like 10 more
Button one;
Button two;
EditText display;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Associate the button variable with the xml reference
one= (Button) findViewById(R.id.bOne);
display= (EditText) findViewById(R.id.editText1);
//When button is clicked, display the text. How do I do this for the rest of my variables?
one.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//String string= Integer.toString(counter);
display.setText("1");
}
});
}
}
The way I'd do this is add the same onClick attribute in XML to every button, like this:
<Button android:onClick="onButtonClick"
... />
and then add the method that you used in that attribute to your activity, differentiating the buttons by id:
public void onButtonClick(View v) {
switch(v.getId()) {
case R.id.button1:
// do something when button 1 is pressed
break;
case R.id.button2:
// do something when button 2 is pressed
break;
// and so on ....
}
}
Alternatively you can use findViewById() to get each button and assign the same listener to all the buttons. Then differentiate by id inside onClick()as shown above. This adds a few useless codelines though, so I think this example here is slightly more clean.
Yes you just need to override the onClick method of the Activity and tell it to implement the OnClickListener:
import com.ewe.R;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class HelloAndroidActivity extends Activity implements OnClickListener {
/** Called when the activity is first created. */
int counter=0;
//Just have two buttons so far, I'm going to have like 10 more
Button one;
Button two;
EditText display;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Associate the button variable with the xml reference
one= (Button) findViewById(R.id.bOne);
display= (EditText) findViewById(R.id.editText1);
//When button is clicked, display the text. How do I do this for the rest of my variables?
one.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//String string= Integer.toString(counter);
display.setText("1");
}
});
}
#Override
public void onClick(View v){
switch (case v.getId()){
case R.id.bOne:
//Put code for bOne here
break;
case R.id.editText1:
//Put code for editText1 here
break;
}
}
}
The following class is intended to display a set of strings contained in an xml file. Within the onCreate method, an array of strings is pulled from a resource file. These strings are a set of corny jokes that are added to an ArrayList of Joke objects (m_arrJokeList), constructed from the strings.
The addJoke method, called within the onCreate method, is intended to display these jokes in a scroll view as text. However, none of this seems to work on either my device or emulator, so something is definitely wrong with the code. I'd like to know how I can fix this as well on some tips on how to work with these views.
Here is the code, not fully implemented.
package edu.calpoly.android.lab2;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
public class SimpleJokeList extends Activity {
// Contains the list Jokes the Activity will present to the user
protected ArrayList<Joke> m_arrJokeList;
// LinearLayout used for maintaining a list of Views that each display Jokes
protected LinearLayout m_vwJokeLayout;
// EditText used for entering text for a new Joke to be added to m_arrJokeList.
protected EditText m_vwJokeEditText;
// Button used for creating and adding a new Joke to m_arrJokeList using the
// text entered in m_vwJokeEditText.
protected Button m_vwJokeButton;
// Background Color values used for alternating between light and dark rows
// of Jokes.
protected int m_nDarkColor;
protected int m_nLightColor;
#Override
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
initLayout();
Resources localRsrc;
localRsrc = this.getResources();
ArrayList<Joke> jokeList = new ArrayList<Joke>();
String[] jokeStrings = localRsrc.getStringArray(R.array.jokeList);
int size = jokeStrings.length;
Joke tempJoke = new Joke();
for(int i=0;i < size;i++)
{
tempJoke.setJoke(jokeStrings[i]);
jokeList.add(tempJoke);
addJoke(tempJoke);
}
}
// Method used to encapsulate the code that initializes and sets the Layout
// for this Activity.
protected void initLayout() {
// TODO
//LinearLayout rootLayout;
m_arrJokeList = new ArrayList<Joke>();
m_vwJokeLayout = new LinearLayout(this); // why pass "this"
m_vwJokeLayout.setOrientation(LinearLayout.VERTICAL);
ScrollView extendedView = new ScrollView(this.getApplicationContext());
extendedView.addView(m_vwJokeLayout);
setContentView(extendedView);
}
// Method used to encapsulate the code that initializes and sets the Event
// Listeners which will respond to requests to "Add" a new Joke to the list.
protected void initAddJokeListeners() {
// TODO
}
// Method used for encapsulating the logic necessary to properly initialize
// a new joke, add it to m_arrJokeList, and display it on screen.
// #param strJoke
// A string containing the text of the Joke to add.
protected void addJoke(Joke jk) {
m_arrJokeList.add(jk);
TextView textJoke = new TextView(this);
textJoke.setText(jk.getJoke());
m_vwJokeLayout.addView(textJoke);
}
}
put
Joke tempJoke = new Joke();
in for loop
for(int i=0;i < size;i++)
{
Joke tempJoke = new Joke();
tempJoke.setJoke(jokeStrings[i]);
jokeList.add(tempJoke);
addJoke(tempJoke);
}
then try it. and let me know what happen.
I am rather new to Android programming in general and am having particular difficulty with the xml/java UI shuffle... I have a layout which I would like to use as the view displayed when a custom, view class is instantiated in the activity class. This much works fine by simply calling
setContentView(R.layout.mylayout) ;
in the activity or from the custom view class through a handle to the activity. The trouble comes when I wish to interact with the widgets on the layout-- I've tried getting a handle on the buttons with
myButton = (Button) findViewById(R.id.mybuttonid);
and separately with
Button myButton = new Button(contextHandle);
myButton = (Button) findViewById(R.layout.mybuttonid);
but in both cases whenever I try to call any methods from the assumed myButton object I get a NullPointerException in the logcat report; evidently myButton is not properly instantiated in either case given above. What is the proper way to instantiate components of a view in a case like this that combines xml and java so that they can call methods dynamically?
thanks,
CCJ
EDIT: Thanks all for the replies, but I think up to 8/1/2011 the advice has been mostly targeted at an implementation wherein the widgets are to be instantiated in the activity class; I wish to instantiate widgets from an xml layout in a custom view class-- a class completely separate from the activity class which extends View and implements its own OnClickListener interface. Below is my code:
MyActivity Class:
package com.ccg.myactivity;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.RadioButton;
public class MyActivity extends Activity implements OnClickListener {
private boolean touched = false;
private RadioButton myRB;
private Button runB;
private CustomView myView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainlayout);
myRB = (RadioButton) findViewById(R.id.testrb);
runB = (Button) findViewById(R.id.goButton);
//set onClick listeners for activity class
runB.setOnClickListener(this);
}
public void onResume(){
super.onResume();
}
public void onClick(View v) {
// do something when the button is clicked
if (myRB.isChecked()){
setContentView(R.layout.mylayout);
myView = new CustomView(this,this); //passing in activity and context
//handles to custom View class
//myView.getAnotherB().setOnClickListener(this); //commented out as we
//don't want to register the custom view's button with the Activty class's
//OnClickListener; instead it should be registered with the custom View class's own
//OnClickListener implementation.
}
else{
Log.d("me","alt click");
}
}
}
CustomView Class:
package com.ccg.myactivity;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
import android.view.View.OnClickListener;
public class CustomView extends View implements OnClickListener{
private Button anotherB;
private Context contextHandle;
private Activity actHandle;
public CustomView(Context context, Activity act) {
super(context);
contextHandle = context;
actHandle = act;
//anotherB = new Button(contextHandle); //this shouldn't be necessary for
//instantiation from XML widget
initCustomView();
}
public void initCustomView(){
anotherB = (Button) findViewById(R.id.nextbutton);
anotherB.setOnClickListener(this);
}
public Button getAnotherB(){
return anotherB;
}
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Log.d("me", "Got the custom click!");
}
}
mainlayout.xml from which the default view is made:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="#+id/widget474"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical">
<RadioGroup android:id="#+id/widget30" android:orientation="horizontal"
android:layout_x="2dip" android:layout_y="57dip" android:layout_width="match_parent"
android:layout_height="wrap_content">
<RadioButton android:layout_height="wrap_content" android:id="#+id/testrb"
android:textSize="15sp" android:text="Run" android:layout_width="wrap_content"
android:textColor="#ffff99ff"></RadioButton>
</RadioGroup>
<Button android:layout_width="wrap_content" android:text="#string/RUN"
android:id="#+id/goButton" android:layout_height="wrap_content"
android:layout_x="222dip" android:layout_y="110dip"></Button>
</LinearLayout>
mylayout.xml from which the custom view's layout is created:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="#+id/widget0"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical">
<Button android:id="#+id/nextbutton" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:text="work!!!"
>
</Button>
</LinearLayout>
okay, if anybody can explain why any method calls from the button object anotherB (anotherB.setOnClickListener(this) above, but also the simpler anotherB.bringToFront()) cause a force close and a nullpointerexception in logcat with the above implementation I would be most appreciative. thanks!
CCJ
I would declare your button outside of onCreate without the contextHandle parameter... The context will be imbedded in your button upon instantiation (as I understand it).
try:
class YOUR_CLASS {
Button myButton;
onCreate() {
myButton = (Button) findViewById(R.id.WHATEVER_YOU_CALLED_IT_IN_XML);
then you can set an onClickListener or other abilities (you can google that, its easy)
myButton.setOnClickListener(myOnClickListener);
myButton.setText("click me!");
}
}
This sometimes happens to me when the import isn't correct. Sometimes Eclipse will fill in the import as:
import android.R;
of course, this will never find your ID. You should either not have an import, or have something like
import com.myco.mytestapp.R;
If you do that, then the first way of doing it is correct:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mylayout);
Button b = (Button) findViewById(R.id.mybutton);
}
Okay, thanks to some advice from the android developers google group I think I've found the answer to at least the most pressing concern (the NPE and force close):
I needed to override onFinishInflate in my custom View class; it is at that point that my XML layout child views (like anotherB) are truly instantiated. The class now looks like this
package com.ccg.myactivity;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
import android.view.View.OnClickListener;
public class CustomView extends View implements OnClickListener{
private Button anotherB;
private Context contextHandle;
private Activity actHandle;
public CustomView(Context context, Activity act) {
super(context);
contextHandle = context;
actHandle = act;
//anotherB = new Button(contextHandle); //this shouldn't be necessary for
//instantiation from XML widget
initCustomView();
}
public void initCustomView(){
anotherB = (Button) findViewById(R.id.nextbutton);
anotherB.setOnClickListener(this);
}
public Button getAnotherB(){
return anotherB;
}
#Override
public void onFinishInflate(){
anotherB.setOnClickListener(this); //it seems any addressing of child
//views of the layout [the widgets] need to be made after the
//framework calls this method.
}
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Log.d("me", "Got the custom click!");
}
}
Now it pulls up the layout properly and does not throw an NPE. Of course, the onClickListener callback still isn't working right (the message 'Got the custom click!' never appears in logcat), but that's another issue...
thanks all
CCJ
Okay, finally had some time to revisit this issue and I believe I've found the answer:
First, before the xml layout or its components can be addressed they need to be inflated. I knew this, but I wasn't sure when exactly they were inflated. It turns out that setContextView (and probably addContextView) trigger xml inflations. In order to have completely modular activity/view classes, I needed to do something like the following:
Activity Class--
package com.ai.ultimap;
import com.ai.ultimap.views.HomeView;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
public class UltiMapActivity extends Activity {
private View hv;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
hv = new HomeView(this);
}
}
Custom View Class-
package com.ai.ultimap.views;
import com.ai.ultimap.R;
import android.app.Activity;
import android.os.Bundle;
import android.view.*;
import android.widget.*;
import android.view.View.OnClickListener;
public class HomeView extends View implements OnClickListener{
private RadioButton twodRB;
private RadioButton threedRB;
private TextView locTV;
private EditText editlocET;
public HomeView(Activity hAct) {
super(hAct);
//THE FOLLOWING LINE INFLATES-- IT (or another function which calls xml inflation)
//MUST COME BEFORE ANY JAVA ADDRESSING OF WIDGETS IN
//THE XML LAYOUT
//Also note that even though you could invoke findViewById from a class extending
//View, in this case you must use hAct.findViewById. I believe this is due to the
//fact that the activity referenced by hAct is the object responsible for inflating
//the xml and thus the widgets need to be instantiated from it.
hAct.setContentView(R.layout.ultimap);
twodRB = (RadioButton) hAct.findViewById(R.id.twodRBV);
threedRB = (RadioButton) hAct.findViewById(R.id.threedRBV);
locTV = (TextView) hAct.findViewById(R.id.locationTV);
editlocET = (EditText) hAct.findViewById(R.id.locationETV);
//After instantiation however they can be freely accessed from java in
//non-activity classes, which is the point; see the next line...
twodRB.setOnClickListener(this);
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
locTV.setText("yo");
}
}
This code works properly to load up the pre-defined xml view ultimap.xml and then address the widgets dynamically from Java (completely outside the activity class), changing the text of the location text view from 'Location' to 'yo' when the twodRB radiobutton is clicked!
Hope this helps some googlers :)
-CCJ
I am working on a project that needs to add buttons dynamically. But whenever I run my application the application force closes. I've learned that the problem is when I try to add buttons.
package com.Feras.TestProject;
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.LinearLayout;
public class TestProject extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
AddAll();
// Set Text for the button in the Old Testament
}
public void AddAll() {
LinearLayout linearLayout = (LinearLayout)findViewById(R.id.layout1);
Button btn = new Button(this);
btn.setText("MyButton");
linearLayout.addView(btn);
}
}
try like this:
linearLayout.addView(
btn,
new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT)
);
there will only occure an error if linearLayout is null, ensure that layout1 is a valid Item of R.layout.main
Try the following in your custom activity class:
this.addContentView(call,
new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));