creating android dialog fragment with custom image above it - android

Our design team came up with this idea... is it possible to create this loop arrow pointing to circle above dialog?

You can create full screen dialog with transparent background.
Then calculate x / y points of this loop and place arrow.
dialog example:
public void showDialog(Context context, View hourView) {
dialog = new Dialog(context, R.style.DreamDialogStyle);
dialog.setContentView(R.layout.dream_custom_add_photo_dialog);
// hourView in your case will be probably view with hour timer
// you need get for this view x and y position on your screen
// then in your dialog layout you need setX() and setY() for your loppView
// but your loopView will be full transparent background
// for position of x and y on screen You can use
// int[] array = new int[2];
// hourView.getLocationOnScreen(array);
// X = array[0] , Y = array[1]
// and in setX() setY() calculate loopSize for position loop on hourView
// And for arrow would be nice if You have image with this arrow.
// then You will need also calculate for your dilogTop and loopLeftDown
// and setAngle() in image for fill arrow line
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
dialog.show();
}
Dialog style for transparent background:
<style name="DreamDialogStyle" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">#android:color/transparent</item>
</style>

Related

Status bar overlay image shifted down in android nought

I am trying to add an image to the status bar in xamarin forms android..
But the image is completely shifted down and coming under the normal status bar color i set in android nougat.
This happened when i updated the xamarin forms version to 2.4.0.74863
in 2.3.4.270 its working fine. Is this the xamrin forms issue or my code issue.
The code i used to draw overlay on status bar is
activity.Window.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);
activity.Window.ClearFlags(WindowManagerFlags.TranslucentStatus);
activity.Window.SetStatusBarColor(Android.Graphics.Color.Transparent);
ViewGroup contentView = (ViewGroup)activity.FindViewById(Android.Resource.Id.Content);
//if (contentView.ChildCount > 1)
//{
// contentView.RemoveViewAt(1);
//}
// get status bar height
int res = activity.Resources.GetIdentifier("status_bar_height", "dimen", "android");
int height = 0;
if (res != 0)
height = activity.Resources.GetDimensionPixelSize(res);
// create new imageview and set resource id
ImageView image = new ImageView(activity);
LinearLayout.LayoutParams params1 = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, height);
params1.Width = LinearLayout.LayoutParams.MatchParent;
image.LayoutParameters = params1;
image.SetImageResource(imageRes);
image.SetScaleType(ImageView.ScaleType.FitXy);
// add image view to content view
contentView.AddView(image);
contentView.SetFitsSystemWindows(true);
I call this as a dependedncy from the xaml page.
EDIT
After i added the flags that #york mentioned the bottom navigation bar has become translucent and the app view went down.
Just need add the following code in your Activity style :
<style name="MyTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
...
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:statusBarColor">#android:color/transparent</item>
</style>
Effect :

Dialog: dim everything except some region

In my application I'm displaying an image inside a dialog. If the user presses the button the dialog appears and takes 80% of the whole screen. The background will be dimmed because that is the default behavior of the Android Dialog.
Dialog dialog = new Dialog(ActQuiz.this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialogInterface) {
//nothing;
}
});
int width = (int) (getResources().getDisplayMetrics().widthPixels * 0.80);
int height = (int) (getResources().getDisplayMetrics().heightPixels * 0.80);
dialog.getWindow().setLayout(width, height);
ImageView imageView = new ImageView(ActQuiz.this);
String uri = "#drawable/" + info.getInfopicture();
int imageResource = getResources().getIdentifier(uri, null, getPackageName());
Drawable myDrawable = ContextCompat.getDrawable(ActQuiz.this, imageResource);
imageView.setImageDrawable(myDrawable);
new PhotoViewAttacher(imageView);
dialog.addContentView(imageView, new RelativeLayout.LayoutParams(width, height));
dialog.show();
So what I want to achieve is to disable the dimming for a Button, which is visible behind the dialog.
Is this possible or can I only remove the dimming for the whole background?
Is this possible or can I only remove the dimming for the whole background?
It's not possible to instruct Dialog to dim everything except some view, or some region. There is no such an API to do that.
What you can do, is to provide your custom drawable as a background to Dialog's window. That drawable would be given a Rect with coordinates of Button and a Rect of the screen. It will draw a dim (basically a semitransparent black color) everywhere except the provided rectangle. Looks like xfermode SrcOut is the mode that should be applied.

Setting a window background behind AlertDialog removes dialog centering

I'm creating an AlertDialog with customized view and window background. Setting a ColorDrawable works as expected, but setting a BitmapDrawable from resources makes the dialog appear right at the top of the screen (instead of centered). (Note: I'm talking of the background behind the dialog (normally a transparent grey, not the dialog's background itself!)
Dialog background (#drawable/dialog_bg):
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/white" />
<corners android:radius="10dp" />
</shape>
Dialog layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/dialog_bg"
android:orientation="vertical">
<!-- dialog contents -->
</LinearLayout>
Code to show dialog with ColorDrawable: -> works
private void showDialog() {
final AlertDialog dialog;
#SuppressLint("InflateParams") final ViewGroup dialogView = (ViewGroup) activity.getLayoutInflater().inflate(R.layout.my_dialog, null);
dialog = new AlertDialog.Builder(activity).setView(dialogView).create();
// this works:
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
dialog.show();
}
Code to show dialog with BitmapDrawable from resources (loading a simple PNG): -> removes centering
private void showDialog() {
final AlertDialog dialog;
#SuppressLint("InflateParams") final ViewGroup dialogView = (ViewGroup) activity.getLayoutInflater().inflate(R.layout.my_dialog, null);
dialog = new AlertDialog.Builder(activity).setView(dialogView).create();
// this sets the background, but un-centers the dialog:
BitmapDrawable drawable = (BitmapDrawable) ResourcesCompat.getDrawable(activity.getResources(), R.drawable.my_bg, null);
dialog.getWindow().setBackgroundDrawable(drawable);
dialog.show();
}
Setting a ColorDrawable works as expected: The background behind the Dialog is colored and the dialog is still centered on screen.
Setting a BitmapDrawable does not work: The background is set but the dialog is moved to the top of the screen.
Things that also didn't work:
loading the drawable with ContextCompat.getDrawable() (which is the same as ResourcesCompat.getDrawable() with the current theme instead of null)
using DisplayMetrics and dialog.getWindow().getAttributes().y (and .x respectively) to calculate margins myself: (height - y) / 2 -> just returns the "normal" dialog margin
setting the gravity to CENTER on either dialog.getWindow().setGravity() or dialog.getWindow().getAttributes().gravity -> this just doesn't change anything
setting the gravity to FILL on either dialog.getWindow().setGravity() or dialog.getWindow().getAttributes().gravity -> this removes dialog margins, but still at the top (even further at the top and left, as margins are removed)
So, does anybody know how to set a background from PNG behind the dialog and keeping its centering on the screen?
We had WindowManger for Dialog to Specify custom window attributes:
The layout params you give here should generally be from values previously retrieved with {#link #getAttributes()}; you probably do not want to blindly create and apply your own, since this will blow away any values set by the framework that you are not interested in.
Just add these property according to your requirement :
/**
* Retrieve the current window attributes associated with this panel.
*
* #return WindowManager.LayoutParams Either the existing window
* attributes object, or a freshly created one if there is none.
*/
WindowManager.LayoutParams params = dialog.getWindow().getAttributes();
params.gravity = Gravity.TOP;
/**
* Set the width and height layout parameters of the window. The default
* for both of these is MATCH_PARENT; you can change them to WRAP_CONTENT
* or an absolute value to make a window that is not full-screen.
*
* #param width The desired layout width of the window.
* #param height The desired layout height of the window.
*
* #see ViewGroup.LayoutParams#height
* #see ViewGroup.LayoutParams#width
*/
dialog.getWindow().setLayout((int) (getScreenWidth(activity)), ViewGroup.LayoutParams.MATCH_PARENT);
dialog.getWindow().setBackgroundDrawableResource(R.drawable.message_email_selected);
/**
* Specify custom window attributes. <strong>PLEASE NOTE:</strong> the
* layout params you give here should generally be from values previously
* retrieved with {#link #getAttributes()}; you probably do not want to
* blindly create and apply your own, since this will blow away any values
* set by the framework that you are not interested in.
*
* #param a The new window attributes, which will completely override any
* current values.
*/
dialog.getWindow().setAttributes(params);
As Example :
final Dialog dialog = new Dialog(getActivity());
WindowManager.LayoutParams params = dialog.getWindow().getAttributes();
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.dialog_view);
// dialog.getWindow().setBackgroundDrawable(null);
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
dialog.getWindow().setLayout(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
dialog.getWindow().setAttributes(params);
dialog.show();
//Access dialog views
TextView txt_cancel = (TextView) dialog.findViewById(R.id.txt_cancel);
So I just solved this issue, although I have to admit it's a bit hacky.
First, I disabled fading behind the dialog
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
and manually "faded" the activity by adding a view to it, overlaying the activity with semi-transparent black:
final ViewGroup dimBackgroundView = new FrameLayout(activity);
float dimAlpha = 0.5f;
dimBackgroundView.setBackgroundColor(Color.BLACK);
dimBackgroundView.setAlpha(dimAlpha);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
activityLayout.addView(dimBackgroundView, params);
This also requires me to manually darken the statusbar on supporting devices (SDK 21+):
final int statusBarColor;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
statusBarColor = activity.getWindow().getStatusBarColor();
activity.getWindow().setStatusBarColor(
Color.rgb((int) (Color.red(statusBarColor) + 255 * dimAlpha),
(int) (Color.green(statusBarColor) + 255 * dimAlpha),
(int) (Color.blue(statusBarColor) + 255 * dimAlpha)));
} else {
statusBarColor = Color.BLACK;
}
Afterwards, I added the intended background to the activity (dialogBgView on top of the semi-transparent black view) and went on adding the dialog as normal.
Since I now added all these views to the activity, I need to remove them on dialog dismissal:
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialogInterface) {
// remove dim
activityLayout.removeView(dimBackgroundView);
// restore original statusbar color
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().setStatusBarColor(statusBarColor);
}
// remove background image
activityLayout.removeView(dialogBgView);
}
});
It works, but it's really not a nice solution. So if anyone discovers a better way, please feel free to post it here.

PopupWindow above status bar of Nexus 7 (and status bars of other devices)

I have a PopupWindow which opens after I click an ImageButton:
// Get the [x, y]-location of the ImageButton
int[] loc = new int[2];
myImageButton.getLocationOnScreen(loc);
// Inflate the tag_popup.xml
LinearLayout viewGroup = (LinearLayout)findViewById(R.id.tagPopupLayout);
LayoutInflater layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View layout = layoutInflater.inflate(R.layout.tag_popup, viewGroup);
// Create the PopupWindow
myPopupWindow = new PopupWindow(ChecklistActivity.this);
myPopupWindow.setContentView(layout);
myPopupWindow.setWindowLayoutMode(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
myPopupWindow.setFocusable(true);
myPopupWindow.setOutsideTouchable(false);
// Clear the default translucent background and use a white background instead
myPopupWindow.setBackgroundDrawable(new ColorDrawable(android.graphics.Color.WHITE));
// Set the content of the TextViews, EditTexts and Buttons of the PopupWindow
setPopupContent(...);
// Displaying the Pop-up at the specified location
myPopupWindow.showAtLocation(layout, Gravity.NO_GRAVITY, 0, loc[1]);
because of the Gravity.NO_GRAVITY, the PopupWindow will be displayed within the borders of the Window. Everything works as intended on my Emulator, but when I run it on my Nexus 7 Tablet, it is partly covered by the Device's bottom status bar.
How can I fix this? Should I somehow get the current PopupWindow's location after the Gravity.NO_GRAVITY took place, then change the y-location to add the Device's Statusbar's height, and then re-draw it? (Will try this, but I think that having the right location to start with instead of re-drawing it is a better solution..)
This is what I came up with:
What we have:
The [x, y]-position we gave to the PopupWindow's showAtLocation-method (we only need the y-position in this, which I named oldY)
What we calculate:
The Popup height
The Status Bar height
The max possible height to be within Window boundaries (screenHeight - statusBarHeight - popupHeight)
What we then check:
We check if the oldY is larger than the maxY
If this is the case, the newY will be the maxY and we re-draw the PopupWindow. If this isn't the case it means we do nothing and just use the oldY as the correct Y-postition.
NOTE 1: I made the code for this, but during debugging it turned out the Status Bar's Height is 0 on both my Emulator and my Nexus Tablet, so just using the screenHeight - popupHeight was enough for me. Still, I included the code to calculate the Bottom Status Bar Height with a boolean in my Config-file to enable/disable this, in case the app is installed on another tablet in the future.
Here it is in code, I just added the description above to make it clear which approach I used to tackle this problem:
// Get the [x, y]-location of the ImageButton
int[] loc = new int[2];
myImageButton.getLocationOnScreen(loc);
// Inflate the popup.xml
LinearLayout viewGroup = (LinearLayout)findViewById(R.id.popup_layout);
LayoutInflater layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View layout = layoutInflater.inflate(R.layout.popup, viewGroup);
// Create the PopupWindow
myPopupWindow = new PopupWindow(ChecklistActivity.this);
myPopupWindow.setContentView(layout);
myPopupWindow.setWindowLayoutMode(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
... // Some more stuff with the PopupWindow's content
// Clear the default translucent background and use a white background instead
myPopupWindow.setBackgroundDrawable(new ColorDrawable(android.graphics.Color.WHITE));
// Displaying the Pop-up at the specified location
myPopupWindow.showAtLocation(layout, Gravity.NO_GRAVITY, 0, loc[1]);
// Because the PopupWindow is displayed below the Status Bar on some Device's,
// we recalculate it's height:
// Wait until the PopupWindow is done loading by using an OnGlobalLayoutListener:
final int[] finalLoc = loc;
if(layout.getViewTreeObserver().isAlive()){
layout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
// This will be called once the layout is finished, prior to displaying it
// So we can change the y-position of the PopupWindow just before that
#Override
public void onGlobalLayout() {
// Get the PopupWindow's height
int popupHeight = layout.getHeight();
// Get the Status Bar's height
int statusBarHeight = 0;
// Enable/Disable this in the Config-file
// This isn't needed for the Emulator, nor the Nexus 7 tablet
// Since the calculated Status Bar Height is 0 with both of them
// and the PopupWindow is displayed at its correct position
if(D.WITH_STATUS_BAR_CHECK){
// Check whether the Status bar is at the top or bottom
Rect r = new Rect();
Window w = ChecklistActivity.this.getWindow();
w.getDecorView().getWindowVisibleDisplayFrame(r);
int barHeightCheck = r.top;
// If the barHeightCheck is 0, it means our Status Bar is
// displayed at the bottom and we need to get it's height
// (If the Status Bar is displayed at the top, we use 0 as Status Bar Height)
if(barHeightCheck == 0){
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0)
statusBarHeight = getResources().getDimensionPixelSize(resourceId);
}
}
// Get the Screen's height:
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int screenHeight = dm.heightPixels;
// Get the old Y-position
int oldY = finalLoc[1];
// Get the max Y-position to be within Window boundaries
int maxY = screenHeight - statusBarHeight - popupHeight;
// Check if the old Y-position is outside the Window boundary
if(oldY > maxY){
// If it is, use the max Y-position as new Y-position,
// and re-draw the PopupWindow
myPopupWindow.dismiss();
myPopupWindow.showAtLocation(layout, Gravity.NO_GRAVITY, 0, maxY);
}
// Since we don't want onGlobalLayout to continue forever, we remove the Listener here again
layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
}
NOTE 2: I've set the tag_popup itself to width = match_parent; height = wrap_content on this line:
myPopupWindow.setWindowLayoutMode(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
and the main layout of this Popup to width = match_parent; height = match_parent:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xml>
<!-- The DOCTYPE above is added to get rid of the following warning:
"No grammar constraints (DTD or XML schema) detected for the document." -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/popup_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#layout/tag_shape"
android:padding="#dimen/default_margin">
... <!-- Popup's Content (EditTexts, Spinner, TextViews, Button, etc.) -->
</RelativeLayout>
NOTE 3: My app is forced to stay in Portrait mode. I haven't test this in Landscape mode, but I assume some modifications should be made (not sure though). EDIT: Tested and it also works in Landscape mode on my two devices. I don't know if this also works in Landscape Mode with the Bottom Bar Height enabled.
Took me some time, but it works now. Hopefully they will fix PopupWindow's Gravity in the future, so it will never be below a Status bar, unless the programmer wants this themselves and change the PopupWindow's settings. Makes things a lot easier..

Android - How to detect transparency of the clicked area of custom shaped buttons

I have some irregular shaped buttons, created as ImageButtons. The "android:src" attribute of the ImageButtons are .PNG files with transparent backgrounds. And the parent layout of these ImageButtons, has a custom background image, which is defined with "android:background" attribute. So the background of the activity is not transparent or just black.
My question is; how can I detect if a click on a button is on the transparent area of the source image, or on the visible part of the source image?
I tried using onTouchListener to get the coordinates of the event and make a decision according to the color of the pixel; but since the background is colorful, I couldn't get to a point.
Any help is very much appreciated. Thanks in advance!
Hi bro i think this link may help you.
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/1.5_r4/android/view/View.java#View.dispatchTouchEvent%28android.view.MotionEvent%29
You need to override this method in your custom button to return false if point is not in the desired area. I suggest you go about it like this:
public static class MyButton extends ImageButton {
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
int iX = (int) event.getX();
int iY = (int) event.getY();
// TODO Or use a more sophisticated, pixel value-based condition
if (!(iX >= 0 & iY >= 0 & iX < TheBitmap.getWidth() & iY < TheBitmap.getHeight())) {
return false;
}
return super.dispatchTouchEvent(event)
}
}

Categories

Resources