I created a custom dialog that I'm dynamically putting views into via a RelativeLayout. Every time the dialog is displayed, it shows all my child views just great, but it has some space at the top that I can not account for. I'm assuming this is reserved for a "title" of the dialog (which I won't have). Is there a way to remove that space and have my custom dialog just wrap the contents that I'm putting in?
here is the xml for the layout:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RelativeLayout
android:id="#+id/handlay"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
incidentally, I've tried just having the relative layout be the parent node, with the same results.
Here is the .java for the custom dialog.
public class HandResults extends Dialog implements DialogInterface {
HandResults hr;
Timer myTimer;
RelativeLayout handrl;
// constructor sets the layout view to handresult layout
public HandResults(Context context) {
super(context);
setContentView(R.layout.handresults);
hr = this;
}
// create a timer to remove the dialog after 3 seconds
public void showHands(){
this.show();
myTimer = null;
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
hr.cancel();
}
}, 3000);
}
}
and here is how I would call the dialog:
HandResults mhr = new HandResults(this);
mhr.showHands();
no matter what I do or how I change the layout file, I always have that buffer at the top, how can I get rid of that?
Put this code into class contstructor or onCreate() method:
requestWindowFeature(Window.FEATURE_NO_TITLE);
It must be before calling setContentView method.
Related
I am working on an app using geolocation and I want to set a layout VISIBLE when close to a point and GONE when too far from the point.
This is my xml :
<LinearLayout
android:visibility="gone"
android:id="#+id/slidePane"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
Then I use the ID in the activity as usual :
declare it in the class attribute :
private LinearLayout slidepane;
set it in the onCreate() method :
slidepane = (LinearLayout) findViewById(R.id.slidePane);
And then I try to update it in onLocationChanged() method as follows :
if (InterestPoint.CalculationByDistance(location, new LatLng(47.247801, -1.551883)) < 0.03) {
Toast.makeText(MainActivity.mContext, "InterestPoint close", Toast.LENGTH_SHORT).show();
slidepane.setVisibility(View.VISIBLE);
} else {
slidepane.setVisibility(View.GONE);
}
So the condition is correct since the Toast appears but the layout does not become visible, why?
Thank you.
EDIT : I am using https://github.com/umano/AndroidSlidingUpPanel and try to set the visibility of the second child (the sliding panel). I didn't see anything in the documentation about visibility. I can still access the children of the LinearLayout but not the container itself (and especialy the visibility).
Replace this:
slidepane.setVisibility(View.VISIBLE);
with this:
runOnUiThread(new Runnable() {
#Override
public void run() {
slidepane.setVisibility(View.VISIBLE);
}
});
Make sure you set the visibility of view at the time of initialization.
#Override
protected void onCreate(Bundle savedInstanceState) {
........
slidepane = (LinearLayout) findViewById(R.id.slidePane);
slidepane.setVisibility(View.GONE);
.......
//onLocationChanged() add ->
if (InterestPoint.CalculationByDistance(location, new LatLng(47.247801, -1.551883)) < 0.03) {
Toast.makeText(MainActivity.mContext, "InterestPoint close", Toast.LENGTH_SHORT).show();
slidepane.setVisibility(View.VISIBLE);
} else {
slidepane.setVisibility(View.GONE);
}
I am using a custom ProgressBar. Now while a task is going on, I am showing the progress bar, but user can still interact with the views and controls.
How do I disable the user interaction on whole view just like a ProgressDialog does , when it is visible.
Do I need to use a transparent view on top of main view and show the progress bar on that view and hide that view once a task is completed.
Or just get the id of my parentView and set it disabled ? But then I won't be able to dim the background, just like what happens when a dialog appears on the view/Activity/Fragment. Right?
I just want to know the way to disallow the user from any interaction while the progressbar is visible.
Thanks
Your question: How to disable the user interaction while ProgressBar is visible in android?
To disable the user interaction you just need to add the following code
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
To get user interaction back you just need to add the following code
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
Here is an example:
Note:I am giving you just an example to show how to disable or retain user interaction
Add a progress bar in your xml.Something like this
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/progressBar"
android:visibility="gone"/>
In MainActivity when a button pressed you show the progressbar and disable the user interaction.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView = (ImageView) findViewById(R.id.imageView);
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
mImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mProgressBar.setVisibility(View.VISIBLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
}
});
}
And when user backPressed you remove the progressbar again retain the user interaction.Something like this
#Override
public void onBackPressed() {
super.onBackPressed();
mProgressBar.setVisibility(View.GONE);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
}
If you want to add a feature of disable and greyed out display, you need to add in your xml layout file a linear layout that fills the parent. Set its background to #B0000000 and its visibilty to GONE. Then programmatically set its visibility to VISIBLE.
Hope this help!
I have fixed this issue by adding root layout to the ProgressBar.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:clickable="true"
android:gravity="center"
android:visibility="gone"
android:id="#+id/progress">
<ProgressBar
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminate="true"
android:indeterminateTintMode="src_atop"
android:indeterminateTint="#color/primary"/>
</LinearLayout>
Made the root layout clickable
android:clickable="true"
NOTE: In my main view, I had RelativeLayout as root and have added above-mentioned code inside the root layout at the last position (last child).
Hope this helps!!
just set:
android:clickable="true"
in your xml
<ProgressBar...
Only this makes magic!
To extend (pun intended) on the accepted Answer :
When you use kotlin you can use extension functions. That way you have a quick and nice looking method for blocking and unblocking UI.
fun AppCompatActivity.blockInput() {
window.setFlags(
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
}
fun AppCompatActivity.unblockInput() {
window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
}
fun AppCompatActivity.blockInputForTask(task: () -> Unit) {
blockInput()
task.invoke()
unblockInput()
}
You can use the blocking and unblocking functions in your activity. Also, you can add more functionality like showing a Toast or something.
When using it in a custom view or any other view, you can simply cast the context to activity and use the functions.
Use blockInputForTask to surround simple linear tasks and blockInputand unblockInput when they are needed in different scopes.
You can use blockInputForTask like this:
blockInputForTask {
// Your lines of code
// Can be multiple lines
}
Use document default method progressbar.setCancelable(false)
Make a dialog with transparent background. The issue with getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); is that when app will go in background and come back user will be able to interact with UI components, a lot more handling. So for blocking UI make a transparent dialog and if you want to set time for hide/show. Do this in a runnable thread. So the solution will be
public class TransparentDialogHelper {
private Dialog overlayDialog;
#Inject
public TransparentDialogHelper() {
}
public void showDialog(Context context) {
if (AcmaUtility.isContextFinishing(context)) {
return;
}
if (overlayDialog == null) {
overlayDialog = new Dialog(context, android.R.style.Theme_Panel);
overlayDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED);
}
overlayDialog.show();
}
public void hideDialog() {
if (overlayDialog == null || AcmaUtility.isContextFinishing(overlayDialog.getContext())) {
return;
}
overlayDialog.cancel();
}
}
-------- Timer
Handler handler = new Handler();
handler.postDelayed( () -> {
view.hideProgress();
}, 2000);
Make your parent layout as Relative Layout & add this :
<RelativeLayout ... >
<other layout elements over which prog bar will appear>
<RelativeLayout android:id="#+id/rl_progress_bar"
android:layout_width="match_parent" android:clickable="true"
android:layout_height="match_parent" >
<ProgressBar android:id="#+id/pb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminateOnly="true"
style="#android:style/Widget.DeviceDefault.ProgressBar"
android:theme="#style/AppTheme.MyProgressBar"
/>
</RelativeLayout>
If you have floating buttons in your UI, they still grab all the focus & remain clickable when the progress bar is visible. for this use : (when your prog bar is visible & re-enable them when you make your prog bar invisible/gone)
fb.setEnabled(false);
I have a customized dialog which i have created using DialogFragment. it uses a view which got one button and an edittext.
in my edittext, i have implemented a textwatcher where if there are values in the edittext, the button becomes visible else it remains invisible.
public class ShowDialog extends DialogFragment {
private Button btnShowBalance;
private EditText balanceInquiryPinInput;
public ShowDialog(){
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View myView = inflater.inflate(R.layout.fragment_balance_inquiry,null);
btnShowBalance= (Button) myView.findViewById(R.id.btnShowBalance);
balanceInquiryPinInput = (EditText) myView.findViewById(R.id.et_balance_inquiry_pin);
balanceInquiryPinInput.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(s.length() > 0){
btnShowBalance.setVisibility(View.VISIBLE);
}else{
btnShowBalance.setVisibility(View.INVISIBLE);
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
btnShowBalance.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showBalance(balanceInquiryPinInput,nameview,ShowDialog.this);
}
});
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(myView);
// Create the AlertDialog object and return it
return builder.create();
}
}
Problem
When i change my screen orientation to (let say) landscape, if i had typed anything to my edittext before changing my orientation, whatever i had typed is still visible in landscape, my button is visible But it becomes unclickable. i cannot click it. i have to remove the dialog by pressing somewhere outside the dialog window or back button and create it again.
How can i make my button remain clickable even when one change the screen orientation?
Note: it is clickable before changing orientation.
EDIT
My dialog is activated by a button which is in a fragment and not activity.
this question is not a duplicate of This one because the latter is an implentation on an activity and it's implementation is unreliable to my view and it's state in question(button)
EDIT xml for my custom dialog layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#044848"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:background="#drawable/check_balance"
>
<EditText
android:layout_width="200dp"
android:layout_height="wrap_content"
android:id="#+id/et_balance_inquiry_pin"
android:layout_marginTop="5dp"
android:gravity="center"
android:background="#drawable/enter_pin_textview"
android:inputType="numberPassword"/>
<Button
android:layout_width="150dp"
android:layout_height="wrap_content"
android:text="OK"
android:id="#+id/btnShowBalance"
android:layout_marginTop="20dp"
android:layout_marginBottom="10dp"
android:textColor="#android:color/white"
android:textSize="20sp"
android:background="#drawable/show_balance_ok_button"
android:visibility="invisible" />
</LinearLayout>
The problem of the button being disabled may be due to the dialog no longer being functional due to the calling view being destroyed in the orientation change. So it may still be visible, but is really an artifact of the previous view before it was destroyed.
You need to use methods that saves the state of your dialog fragment instance when it is created. for example you can call
setRetainInstanceState(true);
in your onCreateDialog method to retain the state of your DialogFragment instance when screen orientation changes.
You may need to overide onDestroyView() to prevent dialog from been destroyed when screen orientation changes. like this
#Override
public void onDestroyView() {
if (getDialog() != null && getRetainInstance())
getDialog().setDismissMessage(null);
super.onDestroyView();
}
Information about this and other fragment methods can been found here.
If you are adding click listeners in Dialog to your buttons, you need to add onclick for your new buttons objects create after onConfigurationChanged.
setting on click listener in xml is good practice for removing problem like this:
so set on click in xml like this :
<Button
android:id="#+id/addnote"
android:onClick="closeDialog"
/>
now in activity call onclick where you want
public void closeDialog(View view) {
dialogObject.dismiss();
}
after using on click in xml no need to call setOnClickListener
I have a need to show a minimally-intrusive non-blocking notification which is not tied to the activity it was shown in (like a Toast) and which is clickable. Anyone have any idea whether or not this is possible? Unfortunately, it appears that Toast notifications (custom or otherwise) are not clickable (i.e. setting an OnClickListener on its views has no effect). All the alternatives that I'm aware of (i.e. AlertDialog, PopupWindow and Crouton) seem to show a notification which is tied to the activity it was shown in (i.e. they won't continue showing when the activity finishes). Any suggestions?
You can use PopupWindow, add an onClickListener and add a handler to auto cancel it after n times (just like the behavior of a toast). Something like this:
public static void showToast(Activity a, String title, String message) {
// inflate your xml layout
LayoutInflater inflater = a.getLayoutInflater();
View layout = inflater.inflate(R.layout.custom_toast,
(ViewGroup) a.findViewById(R.id.toast_layout_root));
// set the custom display
((TextView) layout.findViewById(R.id.title)).setText(title);
((TextView) layout.findViewById(R.id.message)).setText(message);
// initialize your popupWindow and use your custom layout as the view
final PopupWindow pw = new PopupWindow(layout,
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT, true);
// set windowType to TYPE_TOAST (requires API 23 above)
// this will make popupWindow still appear even the activity was closed
pw.setWindowLayoutType(WindowManager.LayoutParams.TYPE_TOAST);
pw.showAtLocation(layout, Gravity.CENTER | Gravity.TOP, 0, 500);
// handle popupWindow click event
layout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// do anything when popupWindow was clicked
pw.dismiss(); // dismiss the window
}
});
// dismiss the popup window after 3sec
new Handler().postDelayed(new Runnable() {
public void run() {
pw.dismiss();
}
}, 3000);
}
xml layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/toast_layout_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000"
android:orientation="vertical"
android:elevation="10dp"
android:padding="20dp">
<TextView
android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#FFF"
android:textStyle="bold"/>
<TextView
android:id="#+id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#FFF"/>
</LinearLayout>
You are right, a Toast object has no way to be interacted with, but there are many libraries out there that will give you the same look and feel as a toast, but with some interactivity. The one I use is https://github.com/JohnPersano/SuperToasts
I think what you need is in fact a PopupWindowwhich can be seen here "http://developer.android.com/reference/android/widget/PopupWindow.html".
Toasts have a very specific task, which is to inform the user, without any input from them. So instead of trying to extend the purpose of the Toast, use the PopupWindow which can be interacted with by the user.
A 'Dialog' type of activity will probably be your best bet.
In manifest:
<activity android:name=".ToastLikeActivity"
android:theme="#android:style/Theme.Dialog"
android:label="#string/label"
></activity>
And timeout the activity within the onCreate():
class ToastLikeActivity extends Activity {
#Override
public void onCreate(Bundle state)
// auto-kill activity after X seconds <-------------------------
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
ToastLikeActivity.this.finish(); // kill after X seconds
}
}
}, VisibleTimeSecs*1000);
}
To display the dialog start it as with any other activity:
Intent i = new Intent(this, ToastLikeActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
And it will show up and automatically go away after X seconds.
Such a popup will not be tied to the caller activity. In fact - it will not even require a caller activity. You
can activate it (bad idea, but possible) even from a service.
You can implement basically any kind of sensitive (i.e. accepting user's clicks) interface you want to
the ToastLikeActivity. Especially: you can make its exteriors transparent, giving it a dialog-likke looks.
How to Create dynamic user interface with events...
Hi Friends i want to create a user interface. in which i will have some buttons and labels
but the number of buttons and lables will be changing time to time depending upon the data retrieved from the server...
Can any one please guide me to do solve this issue... with usefuls links and guidence..
This uses two linear layouts to achieve a grid. The higher level LinearLayout is defined in linearlayout.xml, and holds element views vertically. Within each of these vertical views, a Row (custom LinearLayout) is instanciated, and in doing so, specifies the event handler(s). This LinearLayout holds its elements horizontally.
public class YourActivity extends Activity {
#Override
public void onCreate(Bundle bundle){
super.onCreate(bundle);
setContentView(R.layout.linearlayout);
ViewGroup main = (ViewGroup) findViewById(R.id.linearlayout);
main.addView(new Row(this));
main.addView(new Row(this));
}
private class Row extends LinearLayout {
public Row(Context context) {
super(context);
TextView text = new TextView(context);
Button button = new Button(context);
text.setText("Text");
button.setText("Button");
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "Button Clicked", Toast.LENGTH_SHORT).show();
}
});
this.addView(text);
this.addView(button);
}
}
}
linearlayout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linearlayout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
</LinearLayout>
Is this what you were looking for?