Every time I go to add an Image view to my Linear Layout dynamically I get a null pointer exception.
LinearLayout tables = (LinearLayout) findViewById(R.id.table);
for(int i = 0; i < data.length; i++){
ImageView image = new ImageView(getApplicationContext());
try{
int imgID = getResources().getIdentifier(data[i], "drawable", "package");
image.setImageResource(imgID);
}catch(Exception e){
int imgID = getResources().getIdentifier("nia", "drawable", "package");
image.setImageResource(imgID);
}
tables.addView(image); //NULL POINTER THROWN HERE
}
When I debug, the imgID has a value, so I know its working. I just don't understand why its null if
If this is the line that causes the Null Pointer Exception:
tables.addView(image);
Then tables is null, simply findViewById() did not find any View with the id R.id.table in the current layout being displayed.
(If you want help figuring out why tables is null, please post the layout which you pass to setContentView())
Added from comments
Here is a general way to create a PopupWindow. This uses a LayoutInflator to inflate the layout so that we can access it to dynamically add elements to the layout. (Notice that we scope find to popupLayout.findViewById(...)):
public class Example extends Activity {
private PopupWindow popupWindow;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView text = (TextView) findViewById(R.id.text);
text.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
createPopup(view);
}
});
}
public void createPopup(View view) {
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
View popupLayout = layoutInflater.inflate(R.layout.popup, null);
// Customize popup's layout here
Button dismissButton = (Button) popupLayout.findViewById(R.id.dismiss);
dismissButton.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
popupWindow.dismiss();
}
});
popupWindow = new PopupWindow(popupLayout, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
popupWindow.showAtLocation(view, Gravity.CENTER, 0, 0);
}
}
Understand that the root element in popup.xml should have a background attribute defined otherwise the window is transparent by default.
to check if there is a problem with your XML layout you can try to define the layout programmatically
LinearLayout tables = new LinearLayout(getApplicationContext());
for(int i = 0; i < data.length; i++){
ImageView image = new ImageView(getApplicationContext());
try{
int imgID = getResources().getIdentifier(data[i], "drawable", "package");
image.setImageResource(imgID);
}catch(Exception e){
int imgID = getResources().getIdentifier("nia", "drawable", "package");
image.setImageResource(imgID);
}
tables.addView(image);
}
And adds this view like a ContentView
setContentView(tables);
Related
I am currently having a problem with Android application. I am using a table layout with some views in it. The problem is that it seems like the TextView does not wraps the text correctly. However, when I change swipe between fragments it just resizes and it fits as how its supposed to.
This is what is looks like in the first place when the onCreate function is called.
And this is how it looks when I swipe between fragments.
This is the method I used to set up the views inside the table.
private void initializeBookTable(final List<Book> bookList, View view, final Button modifyBtn, final Button deleteBtn)
{
//Get screen width
DisplayMetrics displaymetrics = new DisplayMetrics();
((Activity)getContext()).getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int screenWidth = displaymetrics.widthPixels;
TableLayout table = view.findViewById(R.id.book_tableLayout);
//Border for the text views
final GradientDrawable gd = new GradientDrawable();
gd.setColor(getResources().getColor(R.color.colorTeal));
gd.setCornerRadius(2);
gd.setStroke(2, 0xFF000000);
//Font for the text views
Typeface font = Typeface.create("casual",Typeface.BOLD);
//Header row
TableRow headerRow = new TableRow(this.getContext());
TableLayout.LayoutParams headerRowParams = new TableLayout.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT,TableRow.LayoutParams.WRAP_CONTENT);
headerRowParams.setMargins(0,1,0,0);
headerRow.setLayoutParams(headerRowParams);
//Header name text view
TextView headerName = new TextView(this.getContext());
headerName.setText(getResources().getString(R.string.book_NAME));
headerName.setBackground(gd);
headerName.setPadding(20,0,20,0);
headerName.setTypeface(font);
headerName.setTextColor(Color.BLACK);
headerName.setMinWidth(screenWidth/4);
headerRow.addView(headerName);
//Header chapter text view
TextView headerChapter = new TextView(this.getContext());
headerChapter.setText(getResources().getString(R.string.book_CHAPTER));
headerChapter.setBackground(gd);
headerChapter.setPadding(20,0,20,0);
headerChapter.setTypeface(font);
headerChapter.setTextColor(Color.BLACK);
headerChapter.setMinWidth(screenWidth/4);
headerRow.addView(headerChapter);
//Header page text view
TextView headerPage = new TextView(this.getContext());
headerPage.setText(getResources().getString(R.string.book_PAGE));
headerPage.setBackground(gd);
headerPage.setPadding(20,0,20,0);
headerPage.setTypeface(font);
headerPage.setTextColor(Color.BLACK);
headerPage.setMinWidth(screenWidth/4);
headerRow.addView(headerPage);
//Header name text view
TextView headerStatus = new TextView(this.getContext());
headerStatus.setText(getResources().getString(R.string.book_STATUS));
headerStatus.setBackground(gd);
headerStatus.setPadding(20,0,20,0);
headerStatus.setTypeface(font);
headerStatus.setTextColor(Color.BLACK);
headerStatus.setMinWidth(screenWidth/4);
headerRow.addView(headerStatus);
//Add row to table
table.addView(headerRow);
for(int i = 0; i < bookList.size(); i++)
{
TableRow row = new TableRow(this.getContext());
//Set text views parameters
TableRow.LayoutParams textViewParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT);
textViewParams.setMargins(0,1,0,1);
row.setLayoutParams(textViewParams);
//Set text views parameters
TextView name = new TextView(this.getContext());
name.setText(bookList.get(i).getName());
name.setBackground(gd);
name.setPadding(20,0,20,0);
name.setLayoutParams(textViewParams);
TextView chapter = new TextView(this.getContext());
chapter.setText(bookList.get(i).getChapter());
chapter.setBackground(gd);
chapter.setPadding(20,0,20,0);
chapter.setLayoutParams(textViewParams);
TextView page = new TextView(this.getContext());
page.setText(bookList.get(i).getPage());
page.setBackground(gd);
page.setPadding(20,0,20,0);
page.setLayoutParams(textViewParams);
TextView status = new TextView(this.getContext());
status.setText(bookList.get(i).getStatus());
status.setBackground(gd);
status.setPadding(20,0,20,0);
status.setLayoutParams(textViewParams);
//Add text views to the row
row.addView(name);
row.addView(chapter);
row.addView(page);
row.addView(status);
row.setClickable(true);
//Click listener for each row
row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
TableRow tableRow = (TableRow) view;
selectedRow = tableRow;
//If the row is already selected (in red) deselect it
TextView textViewCheck = (TextView) tableRow.getChildAt(0);
if(selection && textViewCheck.getText().toString().equals(selectedBook.getName()))
{
for(int i = 0; i < 4; i++)
{
TextView textView = (TextView) tableRow.getChildAt(i);
textView.setBackground(gd);
}
//Disable add and modify buttons when row is deselected
modifyBtn.setEnabled(false);
deleteBtn.setEnabled(false);
selection = false;
selectedBook = null;
}
//If the row is not in red check if there is already a selected row
else
{
if(selection)
{
String message = "Please select only one";
Toast.makeText(getContext(), message, LENGTH_SHORT).show();
}
else
{
for(int i = 0; i < 4; i++)
{
TextView textView = (TextView) tableRow.getChildAt(i);
textView.setBackgroundColor(Color.RED);
}
//Enable add and modify buttons when row is selected
modifyBtn.setEnabled(true);
deleteBtn.setEnabled(true);
TextView nameView = (TextView) tableRow.getChildAt(0);
selectedBook = storage.findBook(nameView.getText().toString());
selection = true;
}
}
}
});
//Set row parameters
TableRow.LayoutParams tableRowParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT,TableRow.LayoutParams.WRAP_CONTENT);
tableRowParams.setMargins(0,1,0,1);
row.setLayoutParams(tableRowParams);
table.addView(row);
}
}
This is my onCreate
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.books_fragment,container,false);
storage = InternalStorage.getInstance(this.getContext());
final Button modifyBtn = view.findViewById(R.id.modifyBtn);
final Button deleteBtn = view.findViewById(R.id.deleteBtn);
//Disable modify and delete buttons
modifyBtn.setEnabled(false);
deleteBtn.setEnabled(false);
this.initializeBookTable(storage.getBookList(),view, modifyBtn, deleteBtn);
Button addBtn = view.findViewById(R.id.addBtn);
addBtn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view) {
Intent intent = new Intent(getActivity(), AddModifyBook.class);
startActivity(intent);
}
});
modifyBtn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
Intent intent = new Intent(getActivity(), AddModifyBook.class);
//Passing the selected book to the AddModifyBook activity
intent.putExtra("selectedBook",selectedBook);
startActivity(intent);
selectedBook = null;
selection = false;
}
});
final TableLayout table = view.findViewById(R.id.book_tableLayout);
deleteBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
storage.removeBook(selectedBook);
selectedBook = null;
selection = false;
modifyBtn.setEnabled(false);
deleteBtn.setEnabled(false);
table.removeView(selectedRow);
}
});
return view;
}
And for onResume I have the default.
Another thing that is happening is that if I just set the background of the name (the first column) with the gradient drawable gd then it works but If I set the rest background of the rest of the columns then I have the problem that I have already explained.
So apparently I have managed to solve the issue by using a gradient drawable for the name and a different gradient drawable for the other properties.
I have a ScrollView with LinearLayout into it.After adding the Layout into my LinearLayout, I wanted to remove the view but it removes only the first view.
I have tried parent.removeView(myView)
My Code for Layout adding :
LayoutInflater inflater = getLayoutInflater();
final View view_top = inflater.inflate(R.layout.layout_top, linear_layout,false);
final View view_bottom = inflater.inflate(R.layout.layout_bottom,linear_layout,false);
final RelativeLayout rel_layout_bottom = (RelativeLayout) view_bottom.findViewById(R.id.relative_bottom);
Button btn_update = (Button) rel_layout_bottom.findViewById(R.id.lst_todo_update);
ImageButton btn_remove = (ImageButton) rel_layout_bottom.findViewById(R.id.lst_btn_delete);
ImageButton btn_Color = (ImageButton) rel_layout_bottom.findViewById(R.id.lst_btn_color);
final RelativeLayout rel_layout_top = (RelativeLayout) view_top.findViewById(R.id.relative_top );
final TextView note_Title = (TextView) rel_layout_top.findViewById(R.id.lst_title );
final TextView note_color = (TextView) rel_layout_top.findViewById(R.id.lst_color_type );
note_Title.setText(note_title);
linear_layout.addView(rel_layout_bottom, 0);
JSONArray jsonArray=queryResult.getResultObjects().get(count).getJSONArray("todo_item");
for (int i = 0; i < jsonArray.length(); i++) {
final View view_middle = inflater.inflate(R.layout.layout_middle, linear_layout, false);
final RelativeLayout rel_layout_middle = (RelativeLayout) view_middle.findViewById(R.id.relative_middle);
final CheckBox note_check ;
final TextView note_content ;
note_content = (TextView) rel_layout_middle.findViewById(R.id.lst_content);
note_check = (CheckBox) rel_layout_middle.findViewById(R.id.lst_check);
btn_remove.setOnClickListener(null);
try {
//Getting data correctly here
linear_layout.addView(view_middle,0);
btn_remove.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
linear_layout.removeView(view_middle); //Not able to remove the view here i.e view_middle
linear_layout.removeView(view_top);
linear_layout.removeView(view_bottom);
}
});
} catch (JSONException e) {
e.printStackTrace();
}
}
linear_layout.addView(rel_layout_top , 0);
}
Any answer Appreciated...Thks
Something like below will solve your problem.
final View[] view_middleArr;
for (int i = 0; i < jsonArray.length(); i++) {
view_middleArr = new View[jsonArray.length()];
view_middleArr[i] = inflater.inflate(R.layout.layout_middle, linear_layout, false);
// ...
btn_remove.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
for (View view_middle : view_middleArr) {
linear_layout.removeView(view_middle);
}
linear_layout.removeView(view_top);
linear_layout.removeView(view_bottom);
}
});
}
Edit: You are using same view_middle reference for all your view_middle istances inside your loop, so you can only remove last view_middle instance with your code.
The code
btn_remove.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
linear_layout.removeView(view_middle); //Not able to remove the view here i.e view_middle
linear_layout.removeView(view_top);
linear_layout.removeView(view_bottom);
}
});
is in a for loop.
It means the click of the button will only remove the view_middle that was lastly added to the LinearLayout, as you are using the same object name.
I have some 40 small images and I want to add those to a layout dynamically.But it results memory error in some devices.
Below is my snippet for adding images to a layout when a button is LinearLayout tables =
LinearLayout tables= (LinearLayout) findViewById(R.id.table);
undo.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
for(int i = 0; i < data.length; i++){
ImageView image = new ImageView(getApplicationContext());
try{
int imgID = getResources().getIdentifier(data[i], "drawable", "package");
image.setImageResource(imgID);
}catch(Exception e){
int imgID = getResources().getIdentifier("nia", "drawable", "package");
image.setImageResource(imgID);
}
tables.addView(image);
}
}
});
can anyone suggest me what I need to do in order to avoid the memory error??
I have a array which I get from another Activity. I want to display it in the current Activity as CheckBox items and then have ability to check some of them and delete by button clicking. I implement it next way:
public void addFiles()
{
LinearLayout layout = (LinearLayout) findViewById(R.id.filesList);
if(!FileManagerActivity.finalAttachFiles.isEmpty())
{
for (int i=0; i<FileManagerActivity.finalAttachFiles.size();i++)
{
View line = new View(this);
line.setLayoutParams(new LayoutParams(1, LayoutParams.MATCH_PARENT));
line.setBackgroundColor(0xAA345556);
informationView= new CheckBox(this);
informationView.setTextColor(Color.BLACK);
informationView.setTextSize(16);
informationView.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
informationView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.file_icon, 0, 0, 0);
informationView.setText(FileManagerActivity.finalAttachFiles.get(i).getName().toString());
informationView.setId(i);
layout.addView(informationView, 0);
layout.addView(line, 1);
layout.postInvalidate();
}
}
}
, and call it in the onCreate() method. it can be added successfully. Then I get items which were checked like this:
btnFilesRemove.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
LinearLayout layout = (LinearLayout) findViewById(R.id.filesList);
View v = null;
for(int i=0; i<FileManagerActivity.finalAttachFiles.size(); i++) {
v = layout.getChildAt(i);
CheckBox checkBox = (CheckBox) findViewById(i);
boolean checked=checkBox.isChecked();
if (checked)
{
Log.i("was checked",checkBox.getText().toString());
ViewGroup parent = (ViewGroup) v.getParent();
parent.removeView(v);
FileManagerActivity.finalAttachFiles.remove(i);
Log.i("this is view,baby",v.toString());
}
}
}
});
But items can't be deleted. And I'm thinking - what is better - to implement it in this way or maybe it will be more efficient with ListView using. I mean to create ArrayAdapter e.t.c..
I'm trying to dynamically and programmatically create ImageButtons and add them to my Scrolling LinearLayout. I've been able to add them, but when I try to add onClickListeners to them, all their view ID's are -1; hence not being able to find out which button was clicked.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OnClickListener imageClickListener;
imageClickListener = new OnClickListener(){
#Override
public void onClick(View v) {
System.out.println("id clicked: " + v.getId());
}
};
for (int i = 0; i<images.length; i++)
{
LinearLayout il = new LinearLayout(this);
il.setOrientation(LinearLayout.HORIZONTAL);
il.setMinimumHeight(LayoutParams.WRAP_CONTENT);
il.setMinimumWidth(LayoutParams.WRAP_CONTENT);
int imageid = 0;
ImageButton ib;
BitmapDrawable imagebd;
imageid = getResources().getIdentifier("drawable/" + images[i], null, getPackageName());
imagebd = resizeImage(imageid);
ib = new ImageButton(this);
ib.setClickable(true);
ib.setOnClickListener(imageClickListener);
ib.setImageDrawable(imagebd);
ib.setMinimumHeight(size);
ib.setMinimumWidth(size);
ib.setMaxHeight(size);
ib.setMaxWidth(size);
imageButtons.add(ib);
il.addView(ib);
System.out.println("id: " + ib.getId());
ll.addView(il);
}
this.setContentView(sv);
}
Why not call ib.setId(i) ?
If you want an id, you have to define it when you create the image button!
ImageButton ib = new ImageButton(this);
ib.setId(i);
Try this