So I have a ListView with list-items that each have different images in them. I have my code setup so that when the user clicks an image, it will show an expanded version of that particular image by using the Dialog class.
However, no matter what code I've tried, it doesn't seem like I can make the Dialog image change! Am I not able to modify layout elements from within an adapter? I could only figure out how to reference my individual list-item images by putting the relevant code within my adapter.
What needs to change, and what am I doing wrong?
Here's the applicable code in my adapter for reference:
viewHolder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(LOG_TAG, "Calling ImageView OnClickListener");
int imageId = currentWord.getImageResourceId();
Dialog aD = new Dialog(mContext);
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
View popupLayout = layoutInflater.inflate(R.layout.popup_image_layout, null);
ImageView popupImageView = (ImageView) popupLayout.findViewById(R.id.popup_imageView);
Glide
.with(mContext)
.load(imageId)
.apply(new RequestOptions().circleCrop())
.into(popupImageView);
aD.setContentView(R.layout.popup_image_layout);
aD.show();
}
});
Thanks for any of your help!
So I ended up figuring the answer out on my own.
Under aD.setContentView(), I should have had popupLayout as the target, which had already had R.layout.popup_image_layout assigned and inflated in the same line... By referencing the layout anew, the code wasn't actually inflating the layout, so there was nothing able to be shown.
So all that needed to be changed was: modifying aD.setContentView(R.layout.popup_image_layout) to aD.setContentView(popupLayout) and now when I click on the individual images in my ListView items, the proper image for each pops up in an expanded ImageView, which is shown by way of the Dialog class.
UPDATE:
Added some extra code in order to make sure that the Dialog is completely removed after being closed. Otherwise, it is kept in memory and the memory use continues to stack and increase indefinitely upon each subsequent Dialog being opened.
Updated code below:
Dialog aD = null;
final int imageId = currentWord.getImageResourceId();
final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
viewHolder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
View popupLayout = layoutInflater.inflate(R.layout.popup_image_layout, null);
final ImageView popupImageView = (ImageView) popupLayout.findViewById(R.id.popup_imageView);
if (aD == null) {
aD = new Dialog(mContext);
aD.getWindow().setBackgroundDrawableResource(R.color.transparent);
}
Log.i(LOG_TAG, "Calling ImageView OnClickListener");
Glide
.with(mContext)
.load(imageId)
.apply(new RequestOptions().circleCrop())
.into(popupImageView);
aD.setContentView(popupLayout);
aD.show();
popupLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
aD.dismiss();
aD = null;
}
});
}
});
Related
I'm trying to show a custom toast exactly into deleted ListView item position. This is all I could do:
Adapter:
private View.OnClickListener onDeleteListener(final int position, final ViewHolder holder) {
return new View.OnClickListener() {
#Override
public void onClick(View v) {
showCustomToast(position, position);
}
};
}
public void showCustomToast(int positionX, int positionY) {
LayoutInflater inflater = LayoutInflater.from(context);
View layout = inflater.inflate(R.layout.toast_layout, null, false);
ImageView icon = (ImageView) layout.findViewById(R.id.toast_image);
TextView message = (TextView) layout.findViewById(R.id.toast_text);
LinearLayout fundoMensagem = (LinearLayout) layout.findViewById(R.id.toast_root);
message.setTextColor(Color.BLACK);
fundoMensagem.setBackgroundResource(R.color.error_colors);
message.setText("Item Deleted!");
Toast toast = new Toast(context);
toast.setDuration(toast.LENGTH_LONG);
toast.setView(layout);
toast.setGravity(positionX, positionX, positionX);
toast.show();
}
But this isn't exactly what I need because the position variable of the onDeleteListener method only get the item index and not the screen position. Someone can help me to show the custom toast at the center of each listview item?
You could use View.getLocationOnScreen() and/or getLocationInWindow() to get the absolute coordinates of a view on the screen, but I don't think a Toast is the right things to be putting there, Toasts are system level notifications, not app level, so it would be a bit of a stretch to try to force it into a position in your app. I think you would be much better served by some sort of custom view.
I'm facing a problem. Not sure what to call it, or what causes it
I'm learning Android SQLite and to train started making a simple note app.
The problem is I have a custom dialog for category select, before opening the dialog everything is fine in the EditText field, but after opening, and closing it the text starts writing over, like creating multiple layers of the same text and the text cursor leaves a line after every symbol. (See "bug demo" GIF of the problem)
Has anyone else seen something like this? What could be causing this, the dialog?
Edit:
So this is the code that takes action when clicking on the star to open the dialog
starred.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(CreateNoteActivity.this);
View mView = getLayoutInflater().inflate(R.layout.dialog_category_select, null);
ListView categoryList = mView.findViewById(R.id.category_list);
Button cancelSelect = mView.findViewById(R.id.cancelSelect);
final CategoryListAdapter adapter = new CategoryListAdapter(CreateNoteActivity.this);
categoryList.setAdapter(adapter);
//get the data and append to a list
Cursor data = myDB.getCategories();
while(data.moveToNext()){
Category thisNote = new Category(data.getInt(0), data.getString(1), data.getString(2));
adapter.add(thisNote);
}
categoryList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, final int i, long l) {
final Category selectedCategory = (Category) adapterView.getItemAtPosition(i);
int duration = Toast.LENGTH_SHORT;
String s = "Category celected: "+selectedCategory.getCategoryName();
Toast toast = Toast.makeText(context, s, duration);
toast.show();
}
});
builder.setView(mView);
final AlertDialog selectCategory = builder.create();
selectCategory.getWindow().setBackgroundDrawable(new ColorDrawable(getResources().getColor(android.R.color.transparent)));
selectCategory.show();
View decorView = getWindow().getDecorView();
decorView.setBackgroundResource(android.R.color.transparent);
int width = (int)(getResources().getDisplayMetrics().widthPixels*0.80);
int height = (int)(getResources().getDisplayMetrics().heightPixels*0.80);
selectCategory.getWindow().setLayout(width, height);
cancelSelect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
selectCategory.dismiss();
}
});
}
});
This answer might help you
Write this after the dialog close
ediText = findViewById(R.id.edit_text);
editText.setSelection(editText.getText().length);
Basically using the above logic, the cursor won't be pointed at the first character of the editText on the dialog close
Noticed that I was trying to set a transparent background to display my custom dialog bcg two times.
So what fixed the problem was removing two lines
*View decorView = getWindow().getDecorView();
decorView.setBackgroundResource(android.R.color.transparent);*
Not sure why it was causing this. Should check what is getDecorView() method. Used it cause found it as a solution to show the custom background.
This line works as well
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(getResources().getColor(android.R.color.transparent)));
Guess this was a case of rubber duck debugging - just had to tell someone about the problem to fix it. Thanks everyone.
Try this code when you dismiss or close the dialog,
edittext.setSelection(editText.getText().toString().trim().length);
i have a problem which the log cat said target must be no null
i want to show an image in a Dialog by onclick button with Picasso Loader.
this my code
viewsim.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(DetailBookingAdmin.this, ""+pathSIM, Toast.LENGTH_SHORT).show();
final Dialog dialog = new Dialog(DetailBookingAdmin.this);
dialog.setContentView(R.layout.view_sim);
dialog.setTitle("SIM");
final ImageView imgsim = (ImageView)v.findViewById(R.id.img_sim);
Picasso.with(v.getContext()).load(pathSIM).into(imgsim);
dialog.show();
}
});
Log cat said in line Picasso.with(v.getContext()).load(pathSIM).into(imgsim); target must be not null. Please help me, thanks in advance.
use layout inflater.
LayoutInflater inflater = getLayoutInflater();
View newView = (View) inflater.inflate(R.layout.view_sim, null);
dialog.setContentView(newView);
final ImageView imgsim = (ImageView)newView.findViewById(R.id.img_sim);
...
Here is what I am aiming for:
I am unsure if I am doing this correctly. There are probably better,more efficient, and cleaner ways to do it, but I need to know how.
This layout was designed in xml and inflated via an inflater. The produced view was then placed into an AlertDialog. Thus, this is seen as an AlertDialog by the user.
My concern is with the tags section at the bottom. I want this to work like how Tumblr tags work. Type a string, hit the button, and a button with that tag name will show up in the blank section below it.
Now, if you click on those buttons (with their respective tag names), they will disappear from the frame.
I have several concerns.
I have trouble implementing listeners. If the AddTag button creates more buttons in the (currently invisible, but present) LinearLayout, then what about the created buttons? How do those buttons implement onClick listeners that will remove themselves from the LinearLayout if they were created in some inner method defined from the AddTag button's onClick method?
I am afraid about having to declare some of these views as FINAL in order to reference them in button methods and inner classes. I am now stuck because of this.
Do I have to define my own layout for the tag buttons? You see, a LinearLayout displays things one after the other, yes? I want to try to recreate how some social networking sites do it. Fill the layout with buttons from top to bottom, left to right. If there is no room left in the current row, go to the next one and add the tag button there. It's basically a dynamic LinearLayout that has autowrapping.
If there are any better ways of implementing this, please let me know a general step by step of what to do. I have not learned Fragments yet, but I think it may be VERY applicable here. Also, should I be creating a class that extends ViewGroup, inflating the XML there, and adding helper methods to handle things? I suppose from a DialogFragment I could then addView(the class I just created) and work from there?
Here is my current code by the way. I am stuck and stumped.
/**
* Opens a view for the user to define their new action and add it to the
* dictionary.
*
* #param view
*/
public void defineNewAction(View view) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
LayoutInflater inflater = this.getLayoutInflater();
View viewToSet = inflater.inflate(
R.layout.define_new_action_window_layout,
null);
final EditText newActionName = (EditText) viewToSet
.findViewById(R.id.set_action_name);
final RadioGroup priorityGroup = (RadioGroup) viewToSet
.findViewById(R.id.radiogroup_set_priority);
final EditText goalTimeHours = (EditText) viewToSet
.findViewById(R.id.set_goal_time_hours);
final EditText goalTimeMinutes = (EditText) viewToSet
.findViewById(R.id.set_goal_time_minutes);
final EditText addTagsInput = (EditText) viewToSet
.findViewById(R.id.add_tags_input);
Button addTagButton = (Button) viewToSet.findViewById(R.id.btn_add_tags);
final ArrayList<String> tags = new ArrayList<String>();
final LinearLayout currentTagsLayout = (LinearLayout) viewToSet
.findViewById(R.id.current_tags);
addTagButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String tag = addTagsInput.getText().toString();
tags.add(tag);
Button newTag = new Button(builder.getContext());
int tagId = tag.hashCode();
if (tagId < 0)
tagId *= -1;
newTag.setId(tagId);
newTag.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Button toRemove = (Button) currentTagsLayout.findViewById(tagId);
currentTagsLayout.removeView(toRemove);
}
});
currentTagsLayout.addView(newTag);
}
});
builder.setTitle("Define your action.");
builder.setView(viewToSet);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
String name = newActionName.getText().toString();
int priority = priorityGroup.getCheckedRadioButtonId();
int goalHours = Integer
.parseInt(goalTimeHours.getText().toString());
int goalMinutes = Integer.parseInt(goalTimeMinutes.getText()
.toString());
}
});
builder.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
I have trouble implementing listeners
There's no trouble. For the functionality you are trying to achieve, you can keep adding buttons and setting OnClickListeners on them. You don't even need to give them an id, or track them in any way. The following code inside your OnClickListener will do:
newTag.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Use the View given to you
currentTagsLayout.removeView(v);
}
});
I am afraid about having to declare some of these views as FINAL
This is how Java works. I haven't noticed any crippling effects of this. You can also declare your variables as global to not have to define them as final. But I don't see why declaring them as final is an issue. Could you provide an example where this is a problem?
Do I have to define my own layout for the tag buttons?
This is something you will have to deal with yourself. It's a design decision. If you need auto-wrapping support, you can look at Android Flow Layout: Link. It's an extended LinearLayout that supports auto-wrap of its contents.
I have not learned Fragments yet, but I think it may be VERY
applicable here
I don't see why they would be.
Note/Aside: Some kind of a check here would be better:
String tag = "";
if (!addTagsInput.getText().toString().equals("")) {
tag = addTagsInput.getText().toString();
} else {
// handle empty string
}
In my activity there are 3 buttons. By clicking on the first button, I want a dialog to appear with a graph (in the layout itself it works fine).
btn1 = (Button)findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog = new Dialog(ChartsDuration.this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.dialog_charts1);
// code to show a graph. Here I have a function that calls drawChartAll(),
// but since the layout is declared outside the dialog it cannot render it to the
// linearlayout, and my graph1 linearlayout will be empty.
dialog.show();
}
});
Tha graph uses data that are queried in functions outside like
public void drawChartAll()
{
//blablabla and this is how I define the layout and render the graph to it:
LinearLayout layout = (LinearLayout) findViewById(R.id.graph1);
mChartView = ChartFactory.getBarChartView(ChartsDuration.this, buildBarDataset(titles, values),renderer,Type.DEFAULT);
mChartView.setBackgroundColor(renderer.getBackgroundColor());
layout.addView(mChartView);
}
So without the dialog, I can easily show the graph in the graph1 LinearLayout e.g below the buttons, because they are "on the same levels", but I want to show the graph in a dialog opened by clicking on a button. Because if I were in a dialog I would do this: LinearLayout layout = (LinearLayout)dialog.findViewById(R.id.graph1); But now I cannot do this, since I am outside the dialog.
How do I reach this layout?
Edit:
user113215 I did this:
in the activity:
LayoutInflater inflater = LayoutInflater.from(ChartsDuration.this);
customDialog = (ViewGroup) inflater.inflate(R.layout.dialog_charts1, null);
btn1 = (Button)findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.setContentView(customDialog);
//queries
dialog.show();
}
});
and in drawChartAll:
public void drawChartAll()
{
//code
LinearLayout layout = (LinearLayout) customDialog.findViewById(R.id.graph1);
}
Is this what you mean? This throws me a nullpointer exception to dialog.setContentView(customDialog); line.
If I understand the problem correctly, you're having trouble manipulating things on the layout that's going into the dialog. Instead of calling setContentView(int), inflate the layout yourself and then use setContentView(View).
LayoutInflater inflater = LayoutInflater.from(this);
ViewGroup customDialog = (ViewGroup) inflater.inflate(R.layout.dialog_charts1, null);
// Do chart things here
// Prefix all calls to findViewById with "customDialog."
LinearLayout layout = (LinearLayout) customDialog.findViewById(R.id.graph1);
mChartView = ChartFactory.getBarChartView(ChartsDuration.this, buildBarDataset(titles, values),renderer,Type.DEFAULT);
mChartView.setBackgroundColor(renderer.getBackgroundColor());
layout.addView(mChartView);
// Put the manipulated layout into the dialog
dialog.setContentView(customDialog);
You can use this same trick to take advantage of the AlertDialog.Builder class while still filling the dialog with a custom layout.
Make the dialogvariable a field in your Activity class. You can reach it from anywhere. You can still use dialog.findviewbyid throughout you Activity. Just make sure setcontentView has been called before you call findviewbyid
Edit: I hope when you wrote since I am outside the dialog. you meant you could not access the variable