I am trying to implement an AlertWindow kind of thing where I am using the instance of WindowsManager to add a View on it from a Service. The View is visible and accessible. But the back/home buttons on the on-screen NavigationBar don't seem to respond. I am new to Android.
Here is a snippet of my code:
mLayout = new LinearLayout(this);
mLayout.setLayoutParams(new WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT));
View view = LayoutInflater.from(this).inflate(R.layout.Mainactivity,
mLayout, true);
mTvErrorMsg = (TextView)view.findViewById(R.id.tv_error_msg);
mChkBoxAppState = (CheckBox)view.findViewById(R.id.chkbox_app_state);
mCancelBtn = (Button)view.findViewById(R.id.btn_action);
mEdtPin.addTextChangedListener(this);
try {
mWindowManager.addView(mLayout, wmlp);
} catch (RuntimeException e) {
SymLog.e(TAG, "Failed to add lock page.", e);
}
Adding the below LayoutParameters solved my issue:
wmlp.flags = WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
wmlp.flags &= ~(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
wmlp.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT | WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
wmlp.format = -1;
wmlp.token = null;
wmlp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE;
Are you sure you are defining the layoutparams right?
new WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT)
This implies the the LinearLayout that you have will take up the parents full width/height. Perhaps change the view to WRAP_CONTENT so it will only take up as much as needed.
Likely this will require more work as it depends WHAT exactly you are trying show.
Related
I cannot find a way to disable quick settings tile in Android programmatically that is a requirement for our enterprise launcher.
Are there any clues beyond the How to disable the notification bar pull-down in Android? and https://e2e.ti.com/support/embedded/android/f/509/t/283260
Is it possible to do? Thanks!
May you start your app in the full screen mode?
like explained here: https://stackoverflow.com/a/8470893/2801860
<activity
android:theme="#android:style/Theme.NoTitleBar.Fullscreen"
....
>
Yes you can do it. I had used the following snippet to disable quick settings.
public static void preventStatusBarExpansion(Context context) {
WindowManager manager = ((WindowManager) context.getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE));
Activity activity = (Activity)context;
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
// this is to enable the notification to recieve touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
int resId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
int result = 0;
if (resId > 0) {
result = activity.getResources().getDimensionPixelSize(resId);
}
localLayoutParams.height = result;
localLayoutParams.format = PixelFormat.TRANSPARENT;
customViewGroup view = new customViewGroup(context);
manager.addView(view, localLayoutParams);
}
Call this method where ever you need. Before calling this method make sure you has screen overlay permission.
However this permission is deprecated in Oreo.
It seems is impossible to do at all.
That is the answer.
No, not impossible. Use ACTION_CLOSE_SYSTEM_DIALOGS to prevent it be pulled down when the screen is locked.
I want to play a gif animation and this view will move on the screen every second, but if I start an activity I need to add this view again and the position will change.
See the attached image below. I need to stick this over every view. Any way to do it?
Create one BaseActivity for all activities in your app to show Overlay View or Layout.
you can inherit BaseActivity on other Activity
You can add gif supported views or layouts
for example i added overlay_layout in my showOverlay method.
you can call showOverlay method where ever you want to show and you can remove with removeOverlay with conditions.
Please note that showOverlay and removeOverlay should be in BaseActivity
void showOverlay(){
LayoutInflater inflater = activity.getLayoutInflater();
layout = inflater.inflate(R.layout.overlay_layout, null);
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.gravity = Gravity.BOTTOM;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.type = WindowManager.LayoutParams.TYPE_APPLICATION;
final WindowManager mWindowManager = (WindowManager);
activity.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
mWindowManager.addView(layout, params);
}
void removeOverlay(){
windowManager.removeView(view);
}
set this view into WindowManager and it will always show on top
I want to add a line above the action bar like in the "pocket"-app. How can i do this?
Here is a picture for example:
Thanks
tomtom
Taking advantage of an Activity's WindowManager, we can draw any view we want on top. Here's some (half-pseudo) code that should help:
// Create an instance of some View that does the actual drawing of the line
View customView = new CustomView(<some context>);
// Figure out the window we have to work with
Rect rect = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
// Make sure the view is measured before doing this
int requestedHeight = customView.getLayoutParams().height;
// setup the params of the new view we'll attach
WindowManager.LayoutParams wlp = new WindowManager.LayoutParams(
rect.width(), requestedHeight,
WindowManager.LayoutParams.TYPE_APPLICATION_PANEL,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT);
// set the parameters so we fit on the top left of the window
wlp.x = 0;
wlp.y = rect.top;
wlp.gravity = Gravity.TOP;
// finally add it to the screen
getWindowManager().addView(header, wlp);
The only thing to be careful is that you can't run that code from onCreate() or any lifecycle method of the Activity because the Window won't have been created yet (You'll get a BadTokenException). One way might be post a Runnable on the Window's DecorView so that your code to add the CustomView runs after the Window is created:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
getWindow().getDecorView().post(<Runnable that execs code above>);
}
As for the actual CustomView that will display that multi-coloured bar, I feel like that's a good exercise :-)
All you'd need to do is have the onDraw() method use canvas.drawRect() with specific x and widths.
Hope that helps.
What Pocket does
As for how Pocket actually does it. If you use HierarchyViewer on the Pocket app, you'll be able to determine that Pocket uses a custom class for their ActionBar. Since they already rebuild all the features of the ActionBar for their needs, in their case, adding the line is like adding a regular View to some ViewGroup.
NOTICE: THIS QUESTION HAS BEEN RESOLVED DUE TO ME CATCHING MY OWN STUPIDITY
I want to add a custom class to a LinearLayout, but for some reason I keep getting a NullPointerException.
Here is the method that deals with the addition:
protected void onPostExecute(String results) {
System.out.println("ON POST EXECUTE : " + results);
try {
if(!results.equals(((MessageBlurb)container.getChildAt(0)).getMessage())){
try {
container.removeViewAt(30);
for (int i = 29; i > 0; i--) {
container.addView(container.getChildAt(i-1), i);
container.removeViewAt(i-1);
}
container.addView(new MessageBlurb(getApplicationContext(), results, Color.BLACK), 0);
} catch (NullPointerException e) {
// TODO: handle exception
}
}
}
catch (Exception e) {
MessageBlurb mb = new MessageBlurb(getApplicationContext(), results, Color.BLACK);
mb.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
System.out.println(mb);
container.addView(mb, 0);
}
}
where MessageBlurb extends ViewGroup, because I have a TextView inside the MessageBlurb.
The MessageBlurb class looks like this:
public MessageBlurb(Context context, String message, int color){
super(context);
myTV = new TextView(context);
this.addView(myTV);
myTV.setText(message);
System.out.println("THE BLURB IS CREATED");
this.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
System.out.println("YOU CLIKED THE BLURB");
}
});
}
I printed out the description of mb, and it gives me a memory location. As well as that, the logcat error points to this line:
container.addView(mb, 0);
The container itself is a LinearLayout defined in the activity_main.xml file. It is initialized through the line of code:
container = (LinearLayout)findViewById(R.id.container);
The id of the Layout in the xml file is also called container
Can someone see what I'm doing wrong?
Thanks!
I'm not 100% sure if this is where the problem is, but the following code looks like it's just asking for trouble:
container.removeViewAt(30);
for (int i = 29; i > 0; i--) {
container.addView(container.getChildAt(i-1), i);
container.removeViewAt(i-1);
}
container.addView(new MessageBlurb(getApplicationContext(), results, Color.BLACK), 0);
It looks like you are trying to remove the last view in the container and add a new MessageBlurb at the top. But you don't need to shift all the views down manually like that, simply adding a new view at position 0 will do all that for you. Try replacing it with this:
container.removeViewAt(30);
container.addView(new MessageBlurb(getApplicationContext(), results, Color.BLACK), 0);
Also, do you have a good reason for using getApplicationContext() when creating the message blurb? Your code looks like its part of an AsyncTask class nested inside an Activity class, so you can and should pass the activity itself as the context (i.e. new MessageBlurb(Activity.this, results, Color.BLACK) or something similar).
Hope that helps!
It turns out that I was being a complete idiot. I looked through my onCreate() and found that I had commented out the line:
setContentView(...)
Even so, I want to thank everyone who replied to this thread.
Sorry for all the trouble! :)
Hi guys i am stuck with image caching. i need to populate Linear Layout with images from web.
I was searching examples how to cache images in android and found these examples:
http://developer.android.com/resources/samples/XmlAdapters/src/com/example/android/xmladapters/ImageDownloader.html
Lazy load of images in ListView
I tried it implement for my code.
String picPath = "https://www.google.lt/logos/classicplus.png";
try {
/*
View v = null;//new View(this);
ImageLoader loader = new ImageLoader(this);
ImageView im = (ImageView)this.findViewById(R.id.image);
loader.DisplayImage(picPath, im);
addImage( im);*/
LayoutInflater inflater =(LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View convertView = inflater.inflate(R.layout.item, null);
ImageView image = (ImageView)convertView.findViewById(R.id.image);
ImageDownloader down = new ImageDownloader();
down.download(picPath, image);
addImage(image);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
public void addImage( View view){
LinearLayout pubLayout = (LinearLayout)findViewById( R.id.scrollerLinearlayout);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
//setting layout_margin
params.setMargins(15, 30, 15, 30);
pubLayout.addView(view,params);
}
However this didn't worked. I believe because i add view to linear layout and when image is downloaded it can't repaint it ?
There are examples how to do image caching using ListView. But what to do if i am not using List View.
I would write my own caching but how to make callback to image downloaded as i want first add image to layout and on callback update it ?
Thanks.
you have to call invalidate on parent view
pubLayout.getParent().invalidate();