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..
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've a case like I'm creating custom layout programmatically inside onCreateView(). For example :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return createLayout(cView);
}
View createLayout(View view) {
LinearLayout linLayout = new LinearLayout(activity);
linLayout.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams linLayoutParam = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
linLayout.setLayoutParams(linLayoutParam);
for (int i = 0; i <= 3; i++) {
TextView tv = new TextView(activity);
tv.setId(i);
tv.setText("TextView");
tv.setLayoutParams(lpView);
linLayout.addView(tv);
}
view = linLayout;
return view;
}
#Override
public void onResume() {
super.onResume();
}
Nah, all I want to ask is how to refresh textview that has an ID from onResume() ? Thanks.
You can hold your textview in hashmap with the key of textview's id. then on your resume. you can get that textview by id and refresh it.
private HashMap<Integer,TextView> textViews = new HashMap<>();
in your on create method when you create this textviews you need to put textview in hashmap.
for (int i = 0; i <= 3; i++) {
TextView tv = new TextView(activity);
tv.setId(i);
tv.setText("TextView");
tv.setLayoutParams(lpView);
linLayout.addView(tv);
textViews.put(i,tv);
}
your onResume method should look like below
#Override
protected void onResume() {
super.onResume();
TextView tv = textViews.get(yourId);
tv.setText("Your Text");
}
Make TextView tv as global and update this tv as usual.
This code programatically generates a layout which consists of views and TextViews in a way that is defined in an array. However, I am trying to make each TextView clickable which displays a toast of a bigger explanation of that TextView . Since the toast needs to be specific to the particular TextView , I am trying to set the TextView using another array of explanations at position i. However, when I try to do this I get the error "Cannot refer to a non final variable inside an inner class defined in a different method."
So I am wondering, how do I get around this? i can't be final because it changes on each loop iteration?
for ( int i = 0; i < formulae.length; i++){
if (formulae[i].equals("horizontalrule")){
View rule = new View(FormulaeActivity.this);
rule.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 2));
rule.setBackgroundColor(0xFF000000);
View spacerbig = new View(FormulaeActivity.this);
spacerbig.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 20));
spacerbig.setBackgroundResource(android.R.color.transparent);
container.addView(rule);
container.addView(spacerbig);
}
else{
View spacersmall1 = new View(FormulaeActivity.this);
spacersmall1.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 5));
spacersmall1.setBackgroundResource(android.R.color.transparent);
tx[i] = new TextView(FormulaeActivity.this);
tx[i].setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 50));
tx[i].setText(Html.fromHtml(formulae[i]));
tx[i].setTextSize(20);
tx[i].setPadding(10, 0, 0, 0);
tx[1].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), Html.fromHtml(explanations[i]), Toast.LENGTH_SHORT).show();
// ^this is the offending line
}
});
container.addView(tx[i]);
container.addView(spacersmall1);
}
Why not have a final variable which will hold the value of i on each iteration.
for ( int i = 0; i < formulae.length; i++){
final int pos = i;
And use it like this on the onClick()
Toast.makeText(getApplicationContext(), Html.fromHtml(explanations[pos])..
Try this,
for ( int i = 0; i < formulae.length; i++){
if (formulae[i].equals("horizontalrule")){
View rule = new View(FormulaeActivity.this);
rule.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 2));
rule.setBackgroundColor(0xFF000000);
View spacerbig = new View(FormulaeActivity.this);
spacerbig.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 20));
spacerbig.setBackgroundResource(android.R.color.transparent);
container.addView(rule);
container.addView(spacerbig);
}
else{
View spacersmall1 = new View(FormulaeActivity.this);
spacersmall1.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 5));
spacersmall1.setBackgroundResource(android.R.color.transparent);
tx[i] = new TextView(FormulaeActivity.this);
tx[i].setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 50));
tx[i].setText(Html.fromHtml(formulae[i]));
tx[i].setTextSize(20);
tx[i].setPadding(10, 0, 0, 0);
container.addView(tx[i]);
container.addView(spacersmall1);
}
}
for(int i=0;i<tx.length;i++)
{
if(tx[i]!=null)
{
tx[i].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(),Html.fromHtml(explanations[i]), Toast.LENGTH_SHORT).show();
// ^this is the offending line
}
});
}
}
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);
I am dynamically creating a table. I am inflating the rows using another layout file.
But the onclick event for these dynamic rows is triggered only after the second time.
Please assist.
private void populateRouteDetails(){
TableRow row;
View[] lArray = new View[24];
View lView = null;
LayoutParams lLayoutParams = new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
for (int current = 0; current < 24; current++) {
row = new TableRow(this);
row.setPadding(0, 1, 0, 1);
LayoutInflater inflator = LayoutInflater.from(getBaseContext());
// inflate child
View item = inflator.inflate(R.layout.linear_row, null);
lArray[current] = item;
item.setPadding(0, 15, 0, 15);
row.addView(item);
row.setGravity(Gravity.CENTER_HORIZONTAL);
busRoute.addView(row, lLayoutParams);
lView = new View(this);
lView.setBackgroundColor(0xFF00FF00);
busRoute.addView(lView,
new ViewGroup.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, 1));
}
for(int lCount = 0;lCount<lArray.length;lCount++){
View lRow = lArray[lCount];
lRow.setClickable(true);
lRow.setFocusable(true);
lRow.setFocusableInTouchMode(true);
lRow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View pView) {
Toast.makeText(BusDetails.this, "Hello",Toast.LENGTH_SHORT).show();
}
});
}
}
What do you mean when you say it work the second time? You could do away with the second loop. Add the listener to "item" in the first loop - just after
item.setPadding(0, 15, 0, 15);
Adding listener at before the view gets added to the row might give expected result.