I have app about surveys. I list all active surveys in RecyclerView.
In the bottom of RecyclerView custom item, I add profile pictures of users who attendant to that survey (like in facebook - seen by bla bla)
I decided to implement imageview to that layout horizontally with params, somehow i couldn't and images are not displaying on item.
Here is my OnBindViewHolder(Other parts work well)
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
Picasso.with(context)
.load(surveyList.get(position).getItem_image())
.into(holder.item_survey_image);
String imageStringList = surveyList.get(position).getItem_survey_users_image();
List<String> splitList = Arrays.asList(imageStringList.split(","));
for(int i=0; i<splitList.size(); i++){
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, 20);
Glide.with(context)
.load(splitList.get(i))
.into(holder.item_survey_users_image);
if (holder.item_survey_users_image.getParent() != null)
((ViewGroup) holder.item_survey_users_image.getParent()).removeView(holder.item_survey_users_image);
holder.item_layout_users.addView(holder.item_survey_users_image, layoutParams);
}
holder.item_survey_head.setText(surveyList.get(position).getItem_survey_head());
holder.item_survey_desc.setText(surveyList.get(position).getItem_survey_desc());
holder.item_survey_amount.setText(surveyList.get(position).getItem_survey_amount());
holder.item_survey_time.setText(surveyList.get(position).getItem_survey_time());
holder.item_survey_users.setText(surveyList.get(position).getItem_survey_users());
holder.item_cardview.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(context, ""+position, Toast.LENGTH_SHORT).show();
}
});
}
how you can tell the picture absence is caused by layoutparams ? however here is how you implement a layoutParams in your OnBindViewHolder, say you have RelativeLayout
RelativeLayout.LayoutParams params
=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT);
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
params.addRule(RelativeLayout.CENTER_HORIZONTAL);
params.setMargins(0, 0, 0, 0); //if you need margins
holder.item_survey_image.setLayoutParams(params);
Related
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);
}
});
After one of rule is added to RelativeLayout, I get a don't very correct result. ID does not apply to element/is applied incorrectly. This affects at rules that must be bound to widget.
As a container, I use ListView and add objects to it through BaseAdapter. This obviously does not give desired result, but after reusing same widget that is returned back to the adapter and reused (element is guaranteed not changing again), rules starting working correctly.
#Override
protected void onCreate(Bundle state) {
super.onCreate(state);
ListView view = new ListView(this);
view.setBackgroundColor(Color.BLACK);
view.setId("files_list".hashCode());
view.setAdapter(new TestAdapter(this));
...
private class TestAdapter extends BaseAdapter {
...
#Override
public View getView(int position, View convertView, View parent) {
if(convertView == null) convertView = inflateView();
// only changes text & pictures, doesn't affecting display
manipulateItem(position, convertView);
return convertView;
...
private View inflateView() {
RelativeLayout layout = new RelativeLayout(context);
layout.setLayoutParams(new ViewGroup.LayoutParams(-1, -2));
ImageView icon = new ImageView(context);
icon.setBackgroundColor(Color.BLACK);
icon.setPadding(20, 20, 20, 20);
icon.setId("file_icon".hashCode());
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(110, -1);
params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
params.rightMargin = 30;
layout.addView(icon, params);
...
LinearLayout additional = new LinearLayout(context);
additional.setOrientation(LinearLayout.VERTICAL);
additional.setGravity(Gravity.RIGHT);
additional.setBackgroundColor(Color.RED);
additional.setPadding(30, 0, 30, 0);
additional.setId(java.lang.String("additional_info").hashCode());
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(-2, -2);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
params.addRule(RelativeLayout.CENTER_IN_PARENT);
layout.addView(additional, params);
...
LinearLayout uniqal = new LinearLayout(context);
uniqal.setOrientation(LinearLayout.VERTICAL);
uniqal.setBackgroundColor(Color.BLUE);
uniqal.setId("uniqal_info".hashCode());
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(-2, -2);
// problem occurs here
params.addRule(RelativeLayout.LEFT_OF, additional.getId());
params.addRule(RelativeLayout.RIGHT_OF, icon.getId());
params.addRule(RelativeLayout.CENTER_IN_PARENT);
layout.addView(uniqal, params);
...
return layout;
}
This is what widget will looks like after first scrolling: elements after first drawing screen
And so, after scrolling and reusing same widget: working screen
After firstly 5 uses (so much got into my test screen), everything becomes fine. For the first time, views don't want to be attached by ID to another widget in any way. Is there a way around this?
Options for inflating layout from application .xml don't suit me
Manual update of layout helped me, however this doesn't work right away and my question remains relevant. Here is modified inflateView code:
private View inflateView() {
...
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(-2, -2);
params.addRule(RelativeLayout.LEFT_OF, additional.getId());
params.addRule(RelativeLayout.RIGHT_OF, icon.getId());
params.addRule(RelativeLayout.CENTER_IN_PARENT);
uniqal.post(new Runnable() {
public void run() {
uniqal.requestLayout();
}
});
layout.addView(uniqal, params);
...
return layout;
}
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.
I have a lot of RadioButtons (which are added dynamically through Java) in a RadioGroup which is in a ScrollView. The problem is that I don't know how to resize it so it fits on the screen. My code:
ConstraintLayout layout = (ConstraintLayout) findViewById(R.id.layout);
RadioGroup radioGroup = new RadioGroup(this);
LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener()
{
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
btnEditFolder.setEnabled(true);
btnViewFolder.setEnabled(true);
}
});
for(int i =0; i<foldersArray.length;i++)
{
RadioButton radioButtonView = new RadioButton(this);
radioButtonView.setText(foldersArray[i]);
radioGroup.addView(radioButtonView, p);
}
ScrollView svFolders = new ScrollView(getApplicationContext());
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
radioGroup.setLayoutParams(params);
radioGroup.getLayoutParams().height = screenHeight - 300;
svFolders.setX(50);
svFolders.setY(100 + btnEditFolder.getMeasuredHeight());
svFolders.addView(radioGroup);
layout.addView(svFolders, p);
The ScrollView is placed further down the y-axis and I think it's still the same height as the screen making it go off the screen.
Here's a screenshot
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