is it possible to add a view to WindowManager in android TV - android-tv

I have a requirement like i need to show some icon when my app was not running on foreground. For this i need to add the view to window manager. is it possible to add view to window manager in android tv.
this is the code i tried
LayoutInflater inflater = LayoutInflater.from(getActivity());
final View layout = inflater.inflate(R.layout.layout_show_on_top_of_view, null);
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.gravity = Gravity.TOP | Gravity.LEFT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.type = WindowManager.LayoutParams.TYPE_TOAST;
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
params.format = PixelFormat.TRANSLUCENT;
params.windowAnimations = 0;
final WindowManager mWindowManager = (WindowManager)
getActivity().getSystemService(Context.WINDOW_SERVICE);
mWindowManager.addView(layout, params);
layout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mWindowManager.removeView(layout);
}
});
i tried different types too but it's not working.

I think what you want to achieve can be done with a transparent Activity, check out this other question/answer: Is it possible to draw overlay over any screen using 3rd party app in android TV?

Related

Change display of JavaFX virtual keyboard

My development system contains of a Windows pc with three displays attached to it. The third display is my touch screen display. I've instructed Windows to use this screen as my touch screen display with the "Tablet PC Settings" from Control Panel.
My application is a simple JavaFX touch screen application containing a TextField. To show the virtual keyboard I've set the following settings to true:
-Dcom.sun.javafx.isEmbedded=true
-Dcom.sun.javafx.touch=true
-Dcom.sun.javafx.virtualKeyboard=javafx
My issue is that the keyboard is showing up, but on the wrong monitor. It shows on the primary monitor, instead of the third monitor that is set to be the touch monitor.
Is there a way to show the virtual keyboard on my touch monitor in the current system configuration? For example by telling the keyboard where it's owner application is so it displays on the correct monitor?
Found out how to change the monitor on which the keyboard is shown, to the monitor where the application is shown.
Attach a change listener to the focused property of your textField. When executing the change listener, retrieve the keyboard popup. Then find the active screen bounds of the monitor where the application is shown and move the keyboard x-coordinate to this location.
By setting autoFix to true, the keyboard will make sure its not (partially) outside your monitor, setting autoFix will adjust the y-coordinate automatically. If you don't set autoFix, you also have to set the y-coordinate manually.
#FXML
private void initialize() {
textField.focusedProperty().addListener(getKeyboardChangeListener());
}
private ChangeListener getKeyboardChangeListener() {
return new ChangeListener() {
#Override
public void changed(ObservableValue observable, Object oldValue, Object newValue) {
PopupWindow keyboard = getKeyboardPopup();
// Make sure the keyboard is shown at the screen where the application is already shown.
Rectangle2D screenBounds = getActiveScreenBounds();
keyboard.setX(screenBounds.getMinX());
keyboard.setAutoFix(true);
}
};
}
private PopupWindow getKeyboardPopup() {
#SuppressWarnings("deprecation")
final Iterator<Window> windows = Window.impl_getWindows();
while (windows.hasNext()) {
final Window window = windows.next();
if (window instanceof PopupWindow) {
if (window.getScene() != null && window.getScene().getRoot() != null) {
Parent root = window.getScene().getRoot();
if (root.getChildrenUnmodifiable().size() > 0) {
Node popup = root.getChildrenUnmodifiable().get(0);
if (popup.lookup(".fxvk") != null) {
return (PopupWindow)window;
}
}
}
return null;
}
}
return null;
}
private Rectangle2D getActiveScreenBounds() {
Scene scene = usernameField.getScene();
List<Screen> interScreens = Screen.getScreensForRectangle(scene.getWindow().getX(), scene.getWindow().getY(),
scene.getWindow().getWidth(), scene.getWindow().getHeight());
Screen activeScreen = interScreens.get(0);
return activeScreen.getBounds();
}

How do you make a ContentPage fullscreen?

In Xamarin.Forms 1.3+, how do you make a ContentPage fullscreen?
The most basic exemple of a ContentPage is the one provided upon creating a Xamarin.Forms Portable project.
public App (){
// The root page of your application
MainPage = new ContentPage {
Content = new StackLayout {
VerticalOptions = LayoutOptions.Center,
Children = {
new Label {
XAlign = TextAlignment.Center,
Text = "Welcome to Xamarin Forms!"
}
}
}
};
}
More info (Android): https://developer.android.com/training/system-ui/immersive.html
Your ContentPage is fullscreen. Only the content in your ContentPage does not fill your entire screen.
You can try something like this:
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
your content page is fullscreen . You can check by changing the background color of your content page. Try this following code
BackgroundColor = Color.White
Step 1 in making a full screen is by hiding the Navigation Bar. This can be controlled while Navigating to the View.
FullScreenVideoPlayerPage fullScreenVideoPage = new FullScreenVideoPlayerPage();
NavigationPage.SetHasNavigationBar(fullScreenVideoPage, false);
await Navigation.PushAsync(fullScreenVideoPage);
Remember to use async keyword in Method Signature when using await.
private async void FullScreenVideoPlayerPage_Clicked(object sender, EventArgs e)
Step 2 is to hide the Android Status Bar. But seems this is not standard with Android. I was not fully successful in completely hiding this bar. But I could hide the status icons by:
using Android.App;
using Android.Views;
//......
// Call this method from the constructor after InitializeComponent ();
public void HideStatusBar()
{
var activity = (Activity)Forms.Context;
var window = activity.Window;
var attrs = window.Attributes;
attrs.Flags |= Android.Views.WindowManagerFlags.Fullscreen;
window.Attributes = attrs;
window.ClearFlags(WindowManagerFlags.ForceNotFullscreen);
window.AddFlags(WindowManagerFlags.Fullscreen);
var decorView = window.DecorView;
var uiOptions =
(int)Android.Views.SystemUiFlags.LayoutStable |
(int)Android.Views.SystemUiFlags.LayoutHideNavigation |
(int)Android.Views.SystemUiFlags.LayoutFullscreen |
(int)Android.Views.SystemUiFlags.HideNavigation |
(int)Android.Views.SystemUiFlags.Fullscreen |
(int)Android.Views.SystemUiFlags.Immersive;
decorView.SystemUiVisibility = (Android.Views.StatusBarVisibility)uiOptions;
window.DecorView.SystemUiVisibility = StatusBarVisibility.Hidden;
}

Structuring a MonoTouch.Dialog application

From the examples at Xamarin.com you can build basic M.T. Dialog apps, but how do you build a real life application?
Do you:
1) Create a single DialogViewController and tree every view/RootElement from there or,
2) Create a DialogViewController for every view and use the UINavigationController and push it on as needed?
Depending on your answer, the better response is how? I've built the example task app, so I understand adding elements to a table, click it to go to the 'next' view for editing, but how to click for non-editing? How to click a button, go next view if answer is number 1?
Revised:
There is probably no one right answer, but what I've come up with seems to work for us. Number 2 from above is what was chosen, below is an example of the code as it currently exists. What we did was create a navigation controller in AppDelegate and give access to it throughout the whole application like this:
public partial class AppDelegate : UIApplicationDelegate
{
public UIWindow window { get; private set; }
//< There's a Window property/field which we chose not to bother with
public static AppDelegate Current { get; private set; }
public UINavigationController NavController { get; private set; }
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
Current = this;
window = new UIWindow (UIScreen.MainScreen.Bounds);
NavController = new UINavigationController();
// See About Controller below
DialogViewController about = new AboutController();
NavController.PushViewController(about, true);
window.RootViewController = NavController;
window.MakeKeyAndVisible ();
return true;
}
}
Then every Dialog has a structure like this:
public class AboutController : DialogViewController
{
public delegate void D(AboutController dvc);
public event D ViewLoaded = delegate { };
static About about;
public AboutController()
: base(about = new About())
{
Autorotate = true;
about.SetDialogViewController(this);
}
public override void LoadView()
{
base.LoadView();
ViewLoaded(this);
}
}
public class About : RootElement
{
static AboutModel about = AboutVM.About;
public About()
: base(about.Title)
{
string[] message = about.Text.Split(...);
Add(new Section(){
new AboutMessage(message[0]),
new About_Image(about),
new AboutMessage(message[1]),
});
}
internal void SetDialogViewController(AboutController dvc)
{
var next = new UIBarButtonItem(UIBarButtonSystemItem.Play);
dvc.NavigationItem.RightBarButtonItem = next;
dvc.ViewLoaded += new AboutController.D(dvc_ViewLoaded);
next.Clicked += new System.EventHandler(next_Clicked);
}
void next_Clicked(object sender, System.EventArgs e)
{
// Load next controller
AppDelegate.Current.NavController.PushViewController(new IssuesController(), true);
}
void dvc_ViewLoaded(AboutController dvc)
{
// Swipe location: https://gist.github.com/2884348
dvc.View.Swipe(UISwipeGestureRecognizerDirection.Left).Event +=
delegate { next_Clicked(null, null); };
}
}
Create a sub-class of elements as needed:
public class About_Image : Element, IElementSizing
{
static NSString skey = new NSString("About_Image");
AboutModel about;
UIImage image;
public About_Image(AboutModel about)
: base(string.Empty)
{
this.about = about;
FileInfo imageFile = App.LibraryFile(about.Image ?? "filler.png");
if (imageFile.Exists)
{
float size = 240;
image = UIImage.FromFile(imageFile.FullName);
var resizer = new ImageResizer(image);
resizer.Resize(size, size);
image = resizer.ModifiedImage;
}
}
public override UITableViewCell GetCell(UITableView tv)
{
var cell = tv.DequeueReusableCell(skey);
if (cell == null)
{
cell = new UITableViewCell(UITableViewCellStyle.Default, skey)
{
SelectionStyle = UITableViewCellSelectionStyle.None,
Accessory = UITableViewCellAccessory.None,
};
}
if (null != image)
{
cell.ImageView.ContentMode = UIViewContentMode.Center;
cell.ImageView.Image = image;
}
return cell;
}
public float GetHeight(UITableView tableView, NSIndexPath indexPath)
{
float height = 100;
if (null != image)
height = image.Size.Height;
return height;
}
public override void Selected(DialogViewController dvc, UITableView tableView, NSIndexPath indexPath)
{
//base.Selected(dvc, tableView, path);
tableView.DeselectRow(indexPath, true);
}
}
#miquel
The current idea of a workflow is an app that starts with a jpg of the Default.png that fades into the first view, with a flow control button(s) that would move to the main app. This view, which I had working previous to M.T.D. (MonoTouch.Dialog), which is a table of text rows with an image. When each row is clicked, it moves to another view that has the row/text in more detail.
The app also supports in-app-purchasing, so if the client wishes to purchase more of the product, then switch to another view to transact the purchase(s). This part was the main reason for switching to M.T.D., as I thought M.T.D. would be perfect for it.
Lastly there would be a settings view to re-enable purchases, etc.
PS How does one know when the app is un-minimized? We would like to show the fade in image again.
I have been asking myself the same questions. I've used the Funq Dependency Injection framework and I create a new DialogViewController for each view. It's effectively the same approach I've used previously developing ASP.NET MVC applications and means I can keep the controller logic nicely separated. I subclass DialogViewController for each view which allows me to pass in to the controller any application data required for that particular controller. I'm not sure if this is the recommended approach but so far it's working for me.
I too have looked at the TweetStation application and I find it a useful reference but the associated documentation specifically says that it isn't trying to be an example of how to structure a MonoTouch application.
I use option 2 that you stated as well, it works pretty nicely as you're able to edit the toolbar options on a per-root-view basis and such.
Option 2 is more feasible, as it also gives you more control on each DialogViewController. It can also helps if you want to conditionally load the view.

Monotouch Async and showing Activity Indicator

I've got the following code being called in view the viewdidload method inside of my UIViewController.
Inside the appdelegate I have a UINavigationController which is instantiated with this aforementioned controller and in turn the UINavigationController is placed inside a UITabViewController which in turn is assigned as the rootviewcontroller.
Inside the controller I'm making an async web call to get the data to populate a table, if I use the loading view code to display an activity indicator I get the following warning in monotouch.
Applications are expected to have a root view controller at the end of application launch
public class LoadingView : UIAlertView
{
private UIActivityIndicatorView _activityView;
public void ShowActivity (string title)
{
Title = title;
this.Show();
// Spinner - add after Show() or we have no Bounds.
_activityView = new UIActivityIndicatorView (UIActivityIndicatorViewStyle.WhiteLarge);
_activityView.Frame = new RectangleF ((Bounds.Width / 2) - 15, Bounds.Height - 50, 30, 30);
_activityView.StartAnimating ();
AddSubview (_activityView);
}
public void Hide ()
{
DismissWithClickedButtonIndex (0, true);
}
}
Any pointers would be gratefully received.
EDIT : I'm already setting the root view controller.
window = new UIWindow (UIScreen.MainScreen.Bounds);
window.RootViewController = tabController;
Full appDelegate code :
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
// create a new window instance based on the screen size
window = new UIWindow (UIScreen.MainScreen.Bounds);
tabController = new UITabBarController();
jobsNavigationController = new UINavigationController(new JobsController());
jobsNavigationController.NavigationBar.BarStyle = UIBarStyle.Black;
jobsNavigationController.TabBarItem.Image = UIImage.FromFile("Images/briefcase.png");
jobsNavigationController.TabBarItem.Title = "Current Positions";
myAccountNavigationController = new UINavigationController(new LoginDialogViewController());
myAccountNavigationController.NavigationBar.BarStyle = UIBarStyle.Black;
myAccountNavigationController.TabBarItem.Image = UIImage.FromFile("images/man.png");
myAccountNavigationController.TabBarItem.Title = "My Account";
tabController.SetViewControllers(new UIViewController[] { jobsNavigationController,myAccountNavigationController,new SettingsDialogViewController()},false);
window.RootViewController = tabController;
// make the window visible
window.MakeKeyAndVisible ();
return true;
}
To avoid this warning (in iOS5) and keep iOS 4.x compatibility you can do the following inside your FinishedLaunching method:
if (UIDevice.CurrentDevice.CheckSystemVersion (5, 0))
window.RootViewController = navigation;
else
window.AddSubview (navigation.View);
Look here for a more complete sample.
window.AddSubview(tabcontroller.view);
Fixed the issue, odd I don't set the rootviewcontroller anymore.

Firebase+RecyclerView: RecyclerView not displaying on application start

I'm using the Android Studio provided class for a tabbed activity that uses Action Bar Tabs with ViewPager. Inside this activity, I'm trying to initialize a RecyclerView with data from a Firebase database.
Problem: On the app's first run, the RecyclerView is empty as shown below.
If I close and reopen the application from within the emulator, my RecyclerView gets populated as it should, as shown below.
Any ideas as to why this might be happening? I have a theory but I haven't been able to find a solution. After trying to read the FragmentPagerAdapter page, I got the impression that the fragments must be static (I don't know what the implications of this might be, so if anyone can shed some light on this it would be appreciated). On the app's first run, it initializes the RecyclerView. It then adds the data from the Firebase database but since the RecyclerView has already been initialized it is empty and is never properly updated. I tried calling the notify... methods to no avail.
StudentFragment's onCreateView method:
private View view;
private Context c;
private RecyclerView mRecyclerView;
private LinearLayoutManager manager;
private Firebase mFirebaseRef;
private FirebaseRecyclerAdapter<Student, ViewHolder> firebaseRecyclerAdapter;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_students, container, false);
mFirebaseRef = new Firebase("<your Firebase link here>");
c = getContext();
//Initializes Recycler View and Layout Manager.
mRecyclerView = (RecyclerView) view.findViewById(R.id.studentRecyclerView);
manager = new LinearLayoutManager(c);
mRecyclerView.setHasFixedSize(true);
firebaseRecyclerAdapter =
new FirebaseRecyclerAdapter<Student, ViewHolder>(
Student.class,
R.layout.single_student_recycler,
ViewHolder.class,
mFirebaseRef
) {
#Override
protected void populateViewHolder(ViewHolder viewHolder, Student student, int i) {
viewHolder.vFirst.setText(student.getFirst());
viewHolder.vLast.setText(student.getLast());
viewHolder.vDue.setText(Double.toString(student.getCurrentlyDue()));
viewHolder.vRadio.setButtonTintList(ColorStateList.valueOf(Color.parseColor(student.getColor())));
Log.d(TAG, "populateViewHolder called");
}
};
mRecyclerView.setAdapter(firebaseRecyclerAdapter);
mRecyclerView.setLayoutManager(manager);
return view;
}
ViewHolder:
public static class ViewHolder extends RecyclerView.ViewHolder {
public final TextView vFirst;
public final TextView vLast;
public final TextView vDue;
public final RadioButton vRadio;
public ViewHolder(View itemView) {
super(itemView);
vFirst = (TextView) itemView.findViewById(R.id.recycler_main_text);
vLast = (TextView) itemView.findViewById(R.id.recycler_sub_text);
vRadio = (RadioButton) itemView.findViewById(R.id.recycler_radio_button);
vDue = (TextView) itemView.findViewById(R.id.recycler_due_text);
}
Homescreen's onCreate method:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_homescreen);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
}
Firebase context is set on another application that starts as soon as the Homescreen activity starts. Any help will be appreciated.
Edit: I was digging through the FirebaseUI GitHub page, which is where the problem most likely lies, and found another user with the exact same problem. It seems that onBindViewHolder isn't called after notifyItemInserted in the FirebaseRecyclerAdapter class. Now to fix it...
In my case this was caused by mRecyclerView.setHasFixedSize(true); If you comment out this line of code the list loads properly. I got my solution from this discussion: https://github.com/firebase/FirebaseUI-Android/issues/204
Let me try, as you say on the question title,
RecyclerView not displaying on application start
so, the
Initializes Recycler View and Layout Manager.
should be declared on the onStart
#Override
public void onStart() {
super.onStart();
mFirebaseRef = new Firebase("<your Firebase link here>");
firebaseRecyclerAdapter = ...
//and so on
Hope it helps!
firebaseRecyclerAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
#Override
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
int friendlyMessageCount = firebaseRecyclerAdapter.getItemCount();
int lastVisiblePosition =
linearLayoutManager.findLastCompletelyVisibleItemPosition();
// If the recycler view is initially being loaded or the
// user is at the bottom of the list, scroll to the bottom
// of the list to show the newly added message.
if (lastVisiblePosition == -1 ||
(positionStart >= (friendlyMessageCount - 1) &&
lastVisiblePosition == (positionStart - 1))) {
linearLayoutManager.scrollToPosition(positionStart);
}
}
});
recyclerListIdeas.setAdapter(firebaseRecyclerAdapter);
** Just add Recyclerview.AdapterDataObserver() . worked for me ! hope it helps :)**
i had the same issue, check the documentation:
https://codelabs.developers.google.com/codelabs/firebase-android/#6
fixed it by adding a data observer:
mFirebaseAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
#Override
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
int friendlyMessageCount = mFirebaseAdapter.getItemCount();
int lastVisiblePosition =
mLinearLayoutManager.findLastCompletelyVisibleItemPosition();
// If the recycler view is initially being loaded or the
// user is at the bottom of the list, scroll to the bottom
// of the list to show the newly added message.
if (lastVisiblePosition == -1 ||
(positionStart >= (friendlyMessageCount - 1) &&
lastVisiblePosition == (positionStart - 1))) {
mMessageRecyclerView.scrollToPosition(positionStart);
}
}
});

Resources