Having trouble removing and then adding views programatically to FrameLayout - java

I am having trouble removing a LinearLayout from a FrameLayout, to then add a new LinearLayout that is populated with EditText generated programatically.
The first time that the view is loaded, I catch a reference to the FrameLayout using findViewById(), and then I make a new LinearLayout programmatically and add a number of EditText to it.
It looks like this
formPlace = (FrameLayout) findViewById(R.id.form_place);
LinearLayout linearView = new LinearLayout(this);
linearView = makeEditText(arrayItems,category);
linearView.setBackgroundColor(Color.GRAY);
linearView.setOrientation(LinearLayout.VERTICAL);
formPlace.addView(linearView);
Next is the function that makes the EditTexts:
private LinearLayout makeEditText(ArrayList<String[]> arrayString, int position){
LinearLayout view = new LinearLayout(this);
arrayInputs = new ArrayList<>();
String[] arrayHints = arrayString.get(position);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
for (int i=0;i<arrayHints.length;i++){
EditText editText = new EditText(this);
Log.i("myApp","tantas veces" + i);
editText.setId(i);
editText.setTextColor(Color.BLACK);
editText.setHint(arrayHints[i]);
editText.setHintTextColor(Color.GRAY);
editText.setLayoutParams(params);
view.addView(editText);
arrayInputs.add(editText);
}
LinearLayout.LayoutParams buttonParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
buttonParams.gravity = Gravity.RIGHT;
android.widget.Button save = new android.widget.Button(this);
save.setText("Guardar");
save.setLayoutParams(buttonParams);
save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i("myApp", "guardar");
saveClicked(category);
}
});
view.addView(save);
android.widget.Button cancel = new android.widget.Button(this);
cancel.setText("cancelar");
cancel.setLayoutParams(buttonParams);
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i("myApp", "cancelar");
cancelClicked();
}
});
view.addView(cancel);
return view;
}
Then, when a spinner event is called, I catch the reference of the FrameLayout and pass .removeAllViews(). This works as intended, and my pevious view is deleted. The problem comes when I try to add new views to the FrameLayout in the makeEditText line:
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, final int position, long id) {
if(firstTime==false) {
FormActivity.this.formPlace.removeAllViews();
LinearLayout auxLinearView = new LinearLayout(FormActivity.this);
auxLinearView = makeEditText(arrayItems, position);
FormActivity.this.formPlace.addView(auxLinearView);
}
firstTime =false;
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
What happens is that the old view is deleted but the new view is not set properly. It only shows 1 element of the 4 is intended to show, and the buttons that I create programmatically don't show at all. And my FrameLayout occupies all the remaining space in my screen, even though is set to wrap content. What it implies is that the view is not behaving as it should.
EDIT:
Here are some Screenshots
Here is how it looks before removeAllViews():
https://dl.pushbulletusercontent.com/tExAXJexe4BfG5sGuKvb1RFtGOFd51nE/Screenshot_2015-05-04-17-54-18.png
Here is how it looks after adding the views to the FrameLayout:
https://dl.pushbulletusercontent.com/JM72D3ZrLwTh0YC9g7PODREyOfCj667P/Screenshot_2015-05-04-17-54-25.png

Related

Getting a view's index in a LinearLayout

So I have a LinearLayout set up in my XML file, and I dynamically add a bunch of CardViews to it through code upon startup of my activity. How can I make it so that when I click on any of the CardViews, I am able to obtain its position?
I tried setting up on an onClickListener for the LinearLayout, as well as an OnClickLIstener for each individual card, but couldn't find a way to obtain the index of the card that was clicked.
I'd really like to know where to put the onClickListener, and how to obtain the position that was clicked so that I can start a new activity based on what was clicked.
Here is my code:
private LinearLayout sLinearLayout;
private CardView[] cardViews;
private Workout[] workouts;
private ViewGroup.LayoutParams params;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.saved_workouts);
Intent intent = getIntent();
Parcelable[] parcelableArrayExtra = intent.getParcelableArrayExtra(MainActivity.EXTRA_WORKOUTS);
workouts = new Workout[parcelableArrayExtra.length];
System.arraycopy(parcelableArrayExtra, 0, workouts, 0, parcelableArrayExtra.length);
sLinearLayout = findViewById(R.id.viewList);
// Set the CardView layoutParams
params = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
populateCardViews();
populateLayout();
}
//TODO: this method will populate the linear layout, filling the list.
private void populateLayout() {
for (CardView cardView : cardViews) {
sLinearLayout.addView(cardView);
}
}
//TODO: this method will fill up the CardViews array with an array of workouts.
private void populateCardViews() {
cardViews = new CardView[workouts.length];
for(int i = 0; i < workouts.length; i++) {
CardView card = new CardView(this);
card.setClickable(true);
card.setLayoutParams(params);
// Set CardView corner radius
card.setRadius(9);
// Set cardView content padding
card.setContentPadding(15, 15, 15, 15);
// Set a background color for CardView
card.setCardBackgroundColor(Color.BLUE);
// Set the CardView maximum elevation
card.setMaxCardElevation(50);
// Set CardView elevation
card.setCardElevation(25);
// Initialize a new TextView to put in CardView
TextView tv = new TextView(this);
tv.setLayoutParams(params);
tv.setText("Workout WorkTime: " + workouts[i].getWorkTime());
tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 30);
tv.setTextColor(Color.WHITE);
card.setTag(workouts[i].getWorkTime());
card.addView(tv);
cardViews[i] = card;
}
}
I think you can setOnClickListener for each individual card. The index of clicked card is i
for (int i = 0; i < workouts.length; i++) {
...
final int finalI = i;
card.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i("TAG", "You click at card: " + finalI);
}
});
}
I not good to add so much layout programmatically. You can use a recycler view and an adapter to show a list of items. You can read this: https://developer.android.com/guide/topics/ui/layout/recyclerview
By the way, in your case: when you create a Cardview, just add onClickListener to it and the index of your Cardview is the index of it in Cardview list.
CardView cardView = new CardView(this);
cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//handle click here
}
});
See if this works.
cardview.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int index = linearLayout.indexOfChild(v);
}
});

How to remove dynamically created imageview from another button onclick?

I have created an ImageView dynamically like below image.It works fine. Now I want to remove view when top cross ImageView is clicked. When I click, it crashes .Please help how to achieve it.
here is what i have done
private void postImage(List<Uri> urilist) {
for(int i=0; i< urilist.size(); i++) {
imgView = new ImageView(getActivity());
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(150, 150);
lp.setMargins(20,10,20,10);
imgView.setLayoutParams(lp);
imgView.setId(i);
Log.d("uri list in loop",""+urilist.get(0));
Glide.with(getActivity())
.load(urilist.get(i))
.into(imgView);
layout.addView(imgView);
imgView1 = new ImageView(getActivity());
LinearLayout.LayoutParams lp1 = new LinearLayout.LayoutParams(50, 50);
lp1.setMargins(0,5,1,80);
imgView1.setLayoutParams(lp1);
imgView1.setId(i);
Log.d("uri list in loop",""+urilist.get(0));
Glide.with(getActivity())
.load(R.drawable.ic_action_cross)
.into(imgView1);
layout.addView(imgView1);
}
imgView1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
layout.removeViewAt(v.getId());
}
});
}
If it is because of the index (which definitely will crash in deletion of the 2nd item) then you can try below
imgView1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ViewGroup parentView = (ViewGroup) v.getParent();
parentView.removeView(v);
}
});
Note: You should not set id of two views as same. Rather use some mathematical formula.
I mean #shakac, you can try like that;
for(int i = 0; i<layout.getChildCount(); i++)
{
if (layout.getChildAt(i).getId() == v.getId()){
layout.removeView(layout.getChildAt(i));
break;
}
}
But as I said on the comment, you will remove the cross button like that.

How to change background of non-visible buttons in GridView (Button adapter) from an activity

My code works only for visible views.
mGridView = (GridView) findViewById(R.id.gridView);
mGridView.setAdapter(new ButtonAdapter(this, list));
Method called when chronometer ticks:
public void setBackground(int i) {
Button button = (Button) mGridView.getChildAt(i);
button.setBackgroundResource(R.drawable.button_shape);
This method causes NPE because getChildAt cannot access non-visible childs.
I tried some solutions found here but no luck so far (android - listview get item view by position - this solution did not causes NPE but was changing background for more buttons in one tick)
What I need is to change first button background on first tick, second button on second tick.. and last button on last tick and stay consistent while scrolling.
My getView method in ButtonAdapter:
public View getView(final int position,
View convertView, ViewGroup parent) {
Button btn;
LayoutInflater inflater = LayoutInflater.from(mContext);
if (convertView == null) {
// if it's not recycled, initialize some attributes
btn = (Button) inflater.inflate(R.layout.button, parent, false);
int width = mContext.getResources().getDimensionPixelSize(R.dimen.gridView_param_width);
int height = mContext.getResources().getDimensionPixelSize(R.dimen.gridView_param_height);
GridView.LayoutParams params = new GridView.LayoutParams(width, height);
btn.setLayoutParams(params);
} else {
btn = (Button) convertView;
}
btn.setText(list.get(position).getName());
btn.setId(position);
btn.setTag(position);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SetGridViewListener activity = (SetGridViewListener) mContext;
activity.onClickGridView(position);
Button btn = (Button)v;
btn.setBackgroundResource(R.drawable.button_shape_clicked);
btn.setClickable(false);
}
});
return btn;
}
I think my problem is in getView method which is probably not recycling well for my purpose.
Thanks in advance.
I have solved it already. I used ViewHolder pattern like here ListView subobject clickable confilct and this method to access buttons from my activity:
public View getViewByPosition(int pos, GridView gridView) {
final int firstListItemPosition = listView.getFirstVisiblePosition();
final int lastListItemPosition = firstListItemPosition + listView.getChildCount() - 1;
if (pos < firstListItemPosition || pos > lastListItemPosition ) {
return gridView.getAdapter().getView(pos, null, listView);
} else {
final int childIndex = pos - firstListItemPosition;
return gridView.getChildAt(childIndex);
}
}
(android - listview get item view by position)
If you would like my concrete solution, write in comment and I will add it.

How can I remove setBackgroundResource when new View is clicked?

I have a Horizontal Listview with a textview. When I click on a textview in the view, that particular textview gets a border.
public View getView(int position, View convertView, ViewGroup parent) {
View retval = LayoutInflater.from(parent.getContext()).inflate(R.layout.minute_listview, null);
Typeface afBold = Typeface.createFromAsset(getAssets(), "fonts/AftenScreen-Bold.ttf");
minuteText = (TextView) retval.findViewById(R.id.title);
Button button = (Button) retval.findViewById(R.id.clickbutton);
button.setOnClickListener(mOnButtonClicked);
minuteText.setText(dataObjects[position]);
minuteText.setTypeface(afBold);
//THIS IS WHERE THE BORDER GETS SET
minuteText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
v.setBackgroundResource(R.drawable.border);
}
});
return retval;
}
Now, how can I remove this border and set it on the next textview thats clicked?
Use this it will give you a white background or a translucent one, in other words it has been removed
WhatEverView.setBackground(new ColorDrawable(Color.TRANSPARENT));
okay full code
int pos -1;// default is -1, which means no one has altered it
// replicate this onclick listener logic
minuteText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(pos != -1){ // it is not -1 that means some1 has altered it
parentView.findViewById(pos).
setBackground(new ColorDrawable(Color.TRANSPARENT));
// the above line searched for the view and changed the background
}
pos = v.getId(); // the id of the new view, keep doing it
v.setBackgroundResource(R.drawable.border);
}
});
so use this for all onclick listeners you want that effect on
Does it fit your requirement?
add this
TextView ClicledTv ;//to save the clicked tv id
then
minuteText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(Clickedtv!=null)
clickedtv.setBackground(R.drawable.anotherOne);
v.setBackgroundResource(R.drawable.border);
clickedTv=minuteText;
}
});

Android How to change data of Textview by clicking on button

First of all, the app looks like this.
How to make - if I click on Add, on its column the textview is updated with value + 1?
I'm creating TextView and Button in a Loop;
for(int i = 0;i < playercountint; i++)
{
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,(100/playercountint)));
layout.setGravity(Gravity.CENTER_HORIZONTAL);
TextView tt = new TextView(this);
tt.setText("0");
tt.setTextSize(14);
tt.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
tt.setGravity(Gravity.CENTER_HORIZONTAL);
Button btadd = new Button(this);
btadd.setText("Add");
btadd.setId(2);
btadd.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
????? what here?
}
});
}
What should be written in onClick function , so only TextView value which is in buttons column is changed.
There is one outer LinearLayout which is horizontally oriented, and those which are created within a loop is vertical Linear Layouts.
Maybe i should create a template for 1 loop iteration?
First make your textview final and them set it's value in onClick
for(int i = 0;i < playercountint; i++)
{
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,(100/playercountint)));
layout.setGravity(Gravity.CENTER_HORIZONTAL);
final TextView tt = new TextView(this);
tt.setText("0");
tt.setTextSize(14);
tt.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
tt.setGravity(Gravity.CENTER_HORIZONTAL);
Button btadd = new Button(this);
btadd.setText("Add");
btadd.setId(2);
btadd.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
tt.setText(String.valueOf(Integer.parseInt(tt.getText())+1));
}
});
}
You can write one function that returns linearlayout:
public View getPlayerView(){
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,(100/playercountint)));
layout.setGravity(Gravity.CENTER_HORIZONTAL);
final TextView tt = new TextView(this);
tt.setText("0");
tt.setTextSize(14);
tt.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
tt.setGravity(Gravity.CENTER_HORIZONTAL);
Button btadd = new Button(this);
btadd.setText("Add");
btadd.setId(2);
btadd.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
tt.setText(String.valueOf(Integer.parseInt(tt.getText())+1));
}
});
layout.add(tt);
layout.add(btadd);
return layout;
}
Call this function in a loop.
tt.setText("something");
tt.invalidate();
my bad I didn't even notice it was a for loop uh you need to hold a reference to the text view.. make your textview final
tt.setText(Integer.parse(tt.getText().toString()) + 1);
But, I strongly recommend you design UI (layout) in the *.xml file!
See more: http://developer.android.com/guide/topics/ui/declaring-layout.html
You should provide your TextView with an unique id (.setId(...)). Having this, in your onClick method simply use something like this:
final TextView tv = (TextView) findViewById(R.id.your_textview_id);
final String cur_text = tv.getText();
Integer plus_one = Integer.valueOf(cur_text);
plus_one++;
tv.setText(plus_one.toString());
Didn't try it but should work.
static int counter = 0;
btn_Add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
counter ++;
tv_Display.setText("Your Total is : " + counter);
}
});

Categories

Resources