I have an AlertDialog in my app that contains an EditText field. This dialog needs to be generated programmatically and should match the way the EditTextPreference dialog looks that is displayed automatically by Android when a user edits text by touching an EditTextPreference. This all works, but the size of the EditText inserted programmatically is too wide and doesn't match the one displayed by the EditTextPreference when touched. The following two images show the problem.
EditText looks like this when added to the AlertDialog using setView():
But should look like this:
Here is the XML code in the XML responsible for the EditTextPreference:
<EditTextPreference
android:title="Enter Name"
android:key="name"
android:defaultValue=""
android:summary=""
android:inputType="textCapSentences|textMultiLine"
android:singleLine="false"
android:gravity="top|left"
android:lines="2"
android:minLines="1"
android:maxLines="2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
/>
And the Java code responsible for my dialog:
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mainActivity);
alertDialog.setTitle("Enter Date");
final EditText input = new EditText(mainActivity);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);
input.setLayoutParams(lp);
input.setGravity(android.view.Gravity.TOP|android.view.Gravity.LEFT);
input.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES|InputType.TYPE_TEXT_FLAG_MULTI_LINE);
input.setLines(1);
input.setMaxLines(1);
input.setText(lastDateValue);
alertDialog.setView(input);
You have to add a container before doing that, e.g LinearLayout
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mainActivity);
alertDialog.setTitle("Enter Date");
LinearLayout container = new LinearLayout(this);
container.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(left, top, right, bottom);
final EditText input = new EditText(mainActivity);
input.setLayoutParams(lp);
input.setGravity(android.view.Gravity.TOP|android.view.Gravity.LEFT);
input.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES|InputType.TYPE_TEXT_FLAG_MULTI_LINE);
input.setLines(1);
input.setMaxLines(1);
input.setText(lastDateValue);
container.addView(input, lp);
alertDialog.setView(container);
I hope it helps :)
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mainActivity);
alertDialog.setTitle("Enter Date");
final EditText input = new EditText(mainActivity);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(left, top, right, bottom);
input.setLayoutParams(lp);
input.setGravity(android.view.Gravity.TOP|android.view.Gravity.LEFT);
input.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES|InputType.TYPE_TEXT_FLAG_MULTI_LINE);
input.setLines(1);
input.setMaxLines(1);
input.setText(lastDateValue);
alertDialog.setView(input);
Please change your code as above and provide desire all margins
You can do this without extra container layout, only add this to your alertDialog :
alertDialog.setOnShowListener(dialog -> {
ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) editText.getLayoutParams();
p.setMargins(50, 20, 50, 20); // You can change the margins for your need
editText.requestLayout();
});
Create an Android XML with the needed and formatted Elements. Inflate the XML/view and add view to dialog button.
This way the UI design and the code is cleaner separated. The Android XML Editor with preview makes it easier to get the wanted optical results.
The Example uses Databinding and so the XML/View is addressed via Databinding DialogEditTextBinding.inflate([...]) and the result is accessed via databinding dialogBinding.editText.getText().toString().
Java Code in Fragment/Activity
final DialogEditTextBinding dialogBinding = DialogEditTextBinding.inflate(getLayoutInflater());
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mainActivity);
alertDialog.setTitle("Enter Date");
alertDialog.setView(dialogBinding);
alertDialog.setPositiveButton("OK",
(dialog, whichButton) -> {
String editText = dialogBinding.editText.getText().toString();
doSomething(editText);
});
Android XML for Dialog extra Elements
dialog_edit_text.xml:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<EditText
android:id="#+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="22dp"
android:layout_marginEnd="22dp"
android:textSize="12sp"
/>
</LinearLayout>
</layout>
PS
PS: The example is combined out of my code and your code, so it may contain errors.
Building on #LeonardoSibela answer, I made this simple function in kotlin to show a dialog with an edittext and a callback.
private fun showEditDialog(title: String, preFill: String, onSubmit: (text: String) -> Unit) {
val editText = EditText(requireContext()).apply {
setText(preFill)
}
val viewContainer = LinearLayout(requireContext()).apply {
orientation = LinearLayout.VERTICAL
val lp = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT
).apply {
setMargins(16.dp, 0, 16.dp, 0)
}
addView(editText, lp)
}
MaterialAlertDialogBuilder(requireContext())
.setView(viewContainer)
.setTitle(title)
.setPositiveButton("Ok") { _, _ -> onSubmit(editText.text.toString()) }
.setNegativeButton("Cancel") { _, _ -> }
.show()
}
And you could use it like this:
showEditDialog("Change name", "") { name ->
viewModel.updateName(name)
}
Related
My activity is a Video Player Activity and its working fine, On some Videos it must throw a message (handleHardwareAccelerationError) if the video is not supported or high quality.
It shows as Toast with message fine.
Now I would like to change this Toast message to show a picture or small icon instead, is this possible? Here is my code for handleHardwareAccelerationError, Thanks in advance.
private void handleHardwareAccelerationError() {
mHardwareAccelerationError = true;
if (mSwitchingView)
return;
Toast.makeText(this, R.string.hardware_acceleration_error, Toast.LENGTH_LONG).show();
}
what I have tried is this but didnt show anything.
private void handleHardwareAccelerationError() {
mHardwareAccelerationError = true;
if (mSwitchingView)
return;
final View popupView = getLayoutInflater().inflate(R.layout.myinforbar, null);
mError = (ImageView) popupView.findViewById(R.id.errornew);
mError.setVisibility(View.VISIBLE);
}
and here is myinforbar.xml
<LinearLayout android:gravity="center_vertical" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="21dp" android:layout_marginLeft="0.0dip" android:layout_marginTop="5.0dip"
android:background="#drawable/button5_background">
<ImageView
android:id="#+id/errornew"
android:src="#drawable/everyone_icon_nearby_cur"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:visibility="invisible"/>
</LinearLayout>
EDITED:
The original activity is long and it can be found here rather then pasting the whole activity you can see it here VideoPlayerActivity
( private void handleHardwareAccelerationError)
New Update...
This is without the message (onHardwareError) applied, I want to see icon inside this bottom little box that popup when video playing (infobar) instead of Toast message.
Toast is farily limited, you cannot show icons.
Edit: Gunjav Dave says it's possible, so it's approach worth a try.
Anyway this free library: SuperToast
can make what you need.
If you prefer to stick to Google's standards you can use, instead, the Snackbars, that don't allow, as far as I know, to put an icon, but can anyway be associated with an action/button, and they are standard.
I can't understand what you try to do with popupView, if you want to use a PopupWindow you have to use a completely different syntax. This Balloon Popup library of mine helps you to make a popup attached to a View, using a PopupWindow, you can also inflate into it a layout, or use it as an example on how to make a PopupWindow.
Edit:
You are inflating a layout inside a view, but this doesn't show the view. Instead, you should use a PopupWindow, and inflate inside it a layout.
This is an example taken from my BalloonPopup library:
// ....
hostedView = ((LayoutInflater) ctx.getSystemService(LAYOUT_INFLATER_SERVICE)).inflate(layoutRes, null);
textView = (TextView) hostedView.findViewById(R.id.text_view);
textView.setText(text);
// ....
popupWindow = new PopupWindow(hostedView, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
In other words, you should be able to do something like
PopupWindow popupWindow = new popupWindow(mError, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
in your code to show the popup window.
These are the essential points of the code, then you can reposition the popup, and eventually keep track of it to edit and re-show it instead of always creating from scratch. Please consider, anyway, to use BalloonPopup library, that does what you need, without getting crazy with animations, display times, window's permanence and positioning. You can just inflate into it your layout, for example with an icon and a text, and make it appear exactly on the center of another View, that can be your (already present) media player.
More edit:
Another very simple solution.
To get it simple, create a RelativeLayout, that hosts all your video player, and then create a simple ImageView in the center of it. Set its visibility to GONE when hidden and to VISIBLE when the error must be shown. Subsequently, you can use a timer or a touchListener to close it making it GONE again.
Try this
private void handleHardwareAccelerationError() {
mHardwareAccelerationError = true;
if (mSwitchingView)
return;
final View popupView = getLayoutInflater().inflate(R.layout.myinforbar, null);
PopupWindow pw = new PopupWindow(popupView , 300, 400, true);
pw.showAtLocation(popupView , Gravity.CENTER, 0, 0);
mError = (ImageView) popupView.findViewById(R.id.errornew);
mError.setVisibility(View.VISIBLE);
}
XML Name or Layout Name would be
<LinearLayout xmlns:androidclass="http://schemas.android.com/apk/res/android"
android:gravity="center_vertical"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/button5_background">
<ImageView
android:id="#+id/errornew"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher"/>
</LinearLayout>
Put This in Class:
LayoutInflater inflater = LayoutInflater.from(this);
View layout= inflater.inflate(R.layout.myinforbar, null);
Toast toast = new Toast(getApplicationContext());
toast.setDuration(Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.setView(layout);
toast.show();
I know this has already been asked, but I tried everything and I couldn't solve my problem.
When I create the views programmatically, they are definitely added. I checked in the debugger and everything is in it's place, even the parent view gets bigger in height because they are using space. But I can't see them. It's like they are below other views or invisible (but they are not. I checked many times...).
This is the xml code where I'm trying to insert the views. I want to insert them where the cursor is (where it's tagged information). I only have it there to show you how it will look like in the end, but this part will be added programmatically.
<LinearLayout
android:id="#+id/llhTestItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:orientation="horizontal">
<TextView
android:id="#+id/tvInformationTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="17sp"
fontPath="fonts/OpenSans-Regular.ttf"
android:text="Sub title: "/> <!-- tvInformationTitle -->
<TextView
android:id="#+id/tvInformation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
fontPath="fonts/OpenSans-Light.ttf"
android:text="information"/> <!-- tvInformation -->
</LinearLayout> <!-- information -->
Below you can see the code that I'm using to add the views just like in the xml above.
#Override
public void onBindViewHolder(SetupViewerHolder holder, int position) {
CardViewItem cardViewItem = cardViewItemList.get(position);
holder.tvTitle.setText(cardViewItem.getCardTitle());
for (int i = 0; i < cardViewItem.getInformationList().size(); i++){
//region Create llhItem
LinearLayout.LayoutParams llhItemParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
llhItemParams.topMargin = dipToPixels(6);
LinearLayout llhItem = new LinearLayout(context);
llhItem.setLayoutParams(llhItemParams);
llhItem.setOrientation(LinearLayout.HORIZONTAL);
//endregion
LinearLayout.LayoutParams tvInformationsParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
//region Create tvInformationTitle
TextView tvInformationTitle = new TextView(context);
tvInformationTitle.setLayoutParams(tvInformationsParams);
tvInformationTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, 17);
if (Build.VERSION.SDK_INT < 23){
tvInformationTitle.setTextAppearance(context, R.style.OpenSansRegular);
} else {
tvInformationTitle.setTextAppearance(R.style.OpenSansRegular);
}
tvInformationTitle.setText(cardViewItem.getInformationList().get(i)[0]);
//endregion
//region Create tvInformation
TextView tvInformation = new TextView(context);
tvInformation.setLayoutParams(tvInformationsParams);
tvInformation.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
if (Build.VERSION.SDK_INT < 23){
tvInformation.setTextAppearance(context, R.style.OpenSansLight);
} else {
tvInformation.setTextAppearance(R.style.OpenSansLight);
}
tvInformation.setText(cardViewItem.getInformationList().get(i)[1]);
//endregion
llhItem.addView(tvInformationTitle);
llhItem.addView(tvInformation);
holder.llvInformation.addView(llhItem);
}
Basically what I'm trying to achieve is to have a recycler view, and each item has only one title, one overflow button, but can have multiple information rows.
Here is a print of this, which I had hard coded in xml previously as a prototype.
I know of some alternative ways of doing this that might work, but for now I would like to have it like this, since everything is working like it should, the views are just "not visible".
Had to use layout.post
holder.llvInformation.post( new Runnable() {
#Override
public void run() {
holder.llvInformation.addView(llhItem);
}
});
Have you tried calling invalidate() after adding the view? Like this:
holder.llvInformation.addView(llhItem);
holder.llvInformation.invalidate();
I'm trying to get my button to create a text field where the user can input information. This way they can only create as many lines as they would like. Also, is there a way to create multiple fields at once?
So, it'll end up being something like this:
"Add Event" (rest of the screen is blank until they click on that button)
Text field 1/ Text field 2/ Text field 3
(once they press that button and of course without the underlines, just an example)
So they can put in information that they want there. If they want another row, they click on the add button again.
Am I supposed to be using an onClickListener? I'm confused as to how I would go about making the button create that field for the user.
public class BudgetScreen extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_budget_screen);
Button addBillExpense = (Button) findViewById(R.id.addBillExpense);
addBillExpense.setOnClickListener(new Button.OnClickListener() {
public void onClick (View v) {
TextView inputField = new TextView(BudgetScreen.this);
}
});
}
}
That is what I have so far. I've been stuck on this for a hot minute. I am aware that I haven't used "inputField" yet.
Suppose you have the following layout xml:
<LinearLayout ...>
<Button .../>
<LinearLayout ...
android:id="#+id/holder"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
in button onClickListener you can have something like:
LinearLayout layout = (LinearLayout) findViewById(R.id.holder);
EditText et = new EditText(this);
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT);
layout.addView(et,lp);
You can change the LayoutParams to get the layout you like.
If you want multiple EditText in a single row, you can do the following:
final int NUM_EDITTEXT_PER_ROW = 3;
LinearLayout layout = (LinearLayout) findViewById(R.id.holder);
Display display = ((WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int width = display.getWidth()/NUM_EDITTEXT_PER_ROW;
LinearLayout tempLayout = new LinearLayout(this);
tempLayout.setOrientation(LinearLayout.HORIZONTAL);
for(int i=0;i<NUM_EDITTEXT_PER_ROW;i++){
EditText et = new EditText(this);
LayoutParams lp = new LayoutParams(width,LayoutParams.WRAP_CONTENT);
tempLayout.addView(et,lp);
}
layout.addView(tempLayout);
in my app i cant use XML layout for some reason now i need to create a layout which its XML code is:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/adlayout"
android:layout_width="match_parent"
android:layout_height="48dp"
android:orientation="vertical" >
<ir.adad.AdView
android:id="#+id/ad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
token="fhsfxfhdghghrgfggh" />
</LinearLayout>
now i need to create a java code which its the same as this XML code! is there any way?how i can do this?
i:ir.adad.adview is a ad services and i put its liberally in my app.
This might help you a bit.
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
int adlayout = 12345; //if you need id of layout somewhere else
//View.generateViewId();Can be used if minSDK= 17
layout.setId(adlayout);
android.view.ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = 48;
params.width = LayoutParams.MATCH_PARENT;
//Below code is used if you need height in dp.
//int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, <HEIGHT>, getResources().getDisplayMetrics());
ir.adad.AdView adView = new ir.adad.AdView(this);
int adViewId = 123456;//Should not be dublicate.
adView.setId(adViewId);
android.view.ViewGroup.LayoutParams paramView = adView.getLayoutParams();
paramView.height = LayoutParams.WRAP_CONTENT;
paramView.width = LayoutParams.WRAP_CONTENT;
layout.addView(adView)
Since I don't know that ad service library I can't help you with its constructor and creation but this should give you something to start working on.
LinearLayout layout = new LinearLayout(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,48);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setLayoutParams(params);
ir.adad.AdView adview = new ir.adad.AdView();
LinearLayout.LayoutParams adviewParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
adview.setLayoutParams(params);
adview.setToken("asdasdas");
layout.addView(adview);
I am trying to develop a chat room for an Android App. I have a created some area for EditText and a corresponding button to Enter the text that is typed by a user.
On clicking on Enter I want to display the typed text on the same screen i.e. whatever text is being typed, it is subsequently being displayed on the same screen. I am using Linear Layout(Horizontal) for my app.
How can I implement this ?? Can someone help me with the code. I am totally new to Android Development Framework. Thanks and Regards.
Its very simple. You create the xml file with one textView and one edittext and one button. Then you handle the event of button click in mainActivity and call onResume from it. Override the onResume so that you can update the textview.
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
TextView text = (TextView) findViewById(R.id.txtView1);
EditText editBox = (EditText)findViewById(R.id.txtBox1);
String str = text.getText().toString();
text.setText(str+" "+editBox.getText().toString());
editBox.setText("");
editBox.setHint("Type in here");
}
You can use 'Toast' to display the msg or use another 'TextView' which is set using 'setText()'
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">
<LinearLayout android:id="#+id/linearLayout1" android:layout_width="match_parent"android:orientation="vertical" android:layout_height="match_parent">
</LinearLayout>
<LinearLayout android:id="#+id/linearLayout2"android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent">
<EditText...
<Button...
</LinearLayout>
</LinearLayout>
setContentView(R.Layout.main);
LinearLayout ll = (LinearLayout)findViewById(R.id.linearLayout1); //Layout where you want to put your new dynamic TextView.
String s=editText.getText().toString(); //Fetching String from your EditText
TextView tv = new TextView(this);
tv.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
tv.setText(s);
ll.addView(tv); //Add TextView inside the Layout.
You can use an one editText for input and one TextView for displaying the typed message:
tvChatWindow = (TextView) findViewById(R.id.tvChatWindow);
etInputWindow = (EditText) findViewById(R.id.etInputWindow);
btnEnter = (Button) findViewById(R.id.btnEnter);
btnEnter.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// send message to other chat clients here
//add a new line break character and the typed string to Chat Window
tvChatWindow.append("\n" + etInputWindow.getText().toString());
//clear the text you have typed on the edittext
etInputWindow.setText("");
}
});