Categories
discuss

Closing Soft Keyboard in Fragment

I found a number of answers to this question but none of them are working for me. I have an Edit text in my Fragment, which gets launched when the application starts. When this Fragment opens, the soft keyboard pops up as well. How do I prevent that from happening? This is what I have in my onCreateView method in my Fragment….

        try {
        InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(
                Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(userName.getWindowToken(), 0);
    }catch(Exception e) {
        e.printStackTrace();
    }

Answer

Try this in onCreateView or onActivityCreated.

getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Categories
discuss

Java calculating past date from today is going into the future

I’m having an issue in Java calculating the current date minus a certain amount of days.

I have:

Date pastDate = new Date(new Date().getTime() - (1000 * 60 * 60 * 24 * 25));

This is returning Tue Feb 16 09:04:18 EST 2016 when it should actually return Tue Dec 28 16:06:11 EST 2015 (25 days into the past).

What’s very strange is that for any number under 25 days works completely fine:

Date pastDate = new Date(new Date().getTime() - (1000 * 60 * 60 * 24 * 24));

As in 24 days into the past returns a predictable Tue Dec 29 16:06:11 EST 2015.

Any help would be appreciated.

Answer

With 24 days, the product remains just below the maximum possible int value, Integer.MAX_VALUE, which is 2,147,483,647. The 24 days product is 2,073,600,000. The 25 days product is 2,160,000,000. The result is overflow and a negative number, resulting in a date in the future.

For such values, use a long literal for the first value (or cast it to a long) to avoid the overflow that comes with exceeding Integer.MAX_VALUE. Note the L appended to 1000L:

(1000L * 60 * 60 * 24 * 25)

This works fine because the desired constructor for Date takes a long.

Date arithmetic is handled more cleanly by using Calendars, where you can explicitly add a negative number of days.

Also, with Java 8+, you can use Instant and its minus method to subtract the time.

Instant.now().minus(24, ChronoUnit.DAYS);
Categories
discuss

Hide floating button when collapsing toolbar is collapsed

I have a coordinator layout containing a collapsing toolbar, a nestedscrollview and a floating button. My floating button is placed at the bottom right end of the collapsing toolbar. I want the button to disappear when the collapsing toolbar is completely collapsed. And be visible in other situation.

My xml :

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="fr.djey.secretapp.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay"
        android:id="@+id/appBar">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapse_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginStart="48dp"
            app:expandedTitleMarginEnd="64dp">

            <ImageView
                android:id="@+id/collapsing_image"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:fitsSystemWindows="true"
                app:layout_collapseMode="parallax"
                android:scaleType="centerCrop"
                android:src="@drawable/welcome"/>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_collapseMode="pin"/>

        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_gravity="fill_vertical"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/content_frame">

        </FrameLayout>

    </android.support.v4.widget.NestedScrollView>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="-60dp"
        android:layout_marginRight="16dp"
        android:src="@android:drawable/ic_dialog_email"
        app:layout_anchor="@id/collapse_toolbar"
        app:layout_anchorGravity="bottom|right|end" />

</android.support.design.widget.CoordinatorLayout>

Is it possible and how?

Answer

Try this small change

<android.support.design.widget.FloatingActionButton
    ...
    app:layout_anchor="@id/appBar"
    app:layout_anchorGravity="bottom|right|end" />
Categories
discuss

Is possible to add css class for a Node object in javaFx?

I want to make a pane with draggable Nodes. When I selected some node, I want to paint some border for this node. Actually, I have it done, but my trouble is, that my solution remove all another styles from Node. It is very ugly solution. I want to do it with adding css classes, but i absolutely don’t know how to do it. When the focus for the node is lost, I want to remove css class. I am new to JavaFx. My code is below:

public void addSelectionControlToNode(Node node) {
node.addEventFilter(MouseEvent.MOUSE_CLICKED, (MouseEvent e) -> {
    if (e.isControlDown()) {
        if (selection.contains(node)) {
            selection.remove(node);
        } else {
            selection.add(node);
            //problematic area below
            node.setStyle("-fx-border-width: 2;
               -fx-border-color: gray; -fx-border-style: solid;");
           //problematic area end
        }
    } else {
        selection.clear();
        selection.add(node);
    }
    System.out.println(selection.size());
});

}

enter image description here

I have seen many tutorials how to work with css in javaFx, but I don understand how can I solve my problem.

Answer

Use a CSS Pseudoclass.

Give all the nodes you are going to drag some fixed style class:

private static final String DRAGGABLE_CLASS = "draggable" ;

// ...

Node node = ... ;
node.getStyleClass().add(DRAGGABLE_CLASS);

Now define a “selected” pseudoclass:

private static final PseudoClass SELECTED_PSEUDO_CLASS =
    PseudoClass.getPseudoClass("selected");

And then do:

public void addSelectionControlToNode(Node node) {
    node.addEventFilter(MouseEvent.MOUSE_CLICKED, (MouseEvent e) -> {
        if (e.isControlDown()) {
            if (selection.contains(node)) {
                selection.remove(node);
                node.pseudoClassStateChanged(SELECTED_PSEUDO_CLASS, false);
            } else {
                selection.add(node);
                node.pseudoClassStateChanged(SELECTED_PSEUDO_CLASS, true);
            }
        } else {
            selection.clear();
            selection.add(node);
            node.pseudoClassStateChanged(SELECTED_PSEUDO_CLASS, true);
        }
        System.out.println(selection.size());
    });
}

Now you can define an external CSS file with:

.draggable {
    /* styles for all draggable nodes */
}
.draggable:selected {
    -fx-border-width: 2;
    -fx-border-color: gray; 
    -fx-border-style: solid;
}
Categories
discuss

How to change activities title in attach()

I want to run a parameterized Instrumentation Test featuring different locales to run the same test with all supported languages.

The observed behavior is that the activity will have the localized title of the first test run also for every following run. So no matter which language my phone is in, the title will be correctly localized for the first parameterized test run, and still be the same for every following one.

While overwriting locales itself works for any resources, it will work only once for the activities title if set by the AndroidManifest.xml.

Activities seem to get their title set once in attach, and whatever is calling attach seems to be caching the title in the locale the app was first launched in.

final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
   ---> CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
    attachBaseContext(context);

Since the resources always get correctly localized, a workaround would be to call setTitle(R.string.title) or just getActionBar().setTitle(R.string.setTitle), but I would like not to change the activities solely for testing purposes.

Question: How can I change the title the activity gets launched with after the first test run? As mentioned above, this seems to get cached and not properly updated, and killing the app to restart it will fail the instrumentation test.

Test setup

The whole test project can be found here on GitHub (Localization.java contains the currently failing unit tests with the issue described here) and is using a Parameterized Unit Test in in conjunction with UIAutomator.

The goal is to take a batch of screenshots without knowing too much about the app itself (UIAutomator), and the app not having to be modified for the test either.

Changing the locale:

I’m successfully changing the locale before every test, and my texts get correctly displayed by doing the following, also I have multiple assertions in place making sure that the resources are in fact the right locale.

public LocalizationTest(Locale locale) {
    mLocale = locale;
    Configuration config = new Configuration();
    Locale.setDefault(mLocale);
    config.setLocale(mLocale);

    Resources resources = InstrumentationRegistry.getTargetContext().getResources();
    resources.updateConfiguration(config, resources.getDisplayMetrics());

    resources.flushLayoutCache();
}

What doesn’t work:

I obviously tried setting the locale in the same way on the target context, the application context, and the activity (which would probably be too late anyways).

I see that attach gets called from Instrumentation, but just creating a new App and trying to launch the activity will not localize the title either.

Intent intent = context.getPackageManager().getLaunchIntentForPackage(BuildConfig.APPLICATION_ID);
context = InstrumentationRegistry.getInstrumentation().newApplication(App.class,
                InstrumentationRegistry.getTargetContext());
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);

Answer

The title string gets cached within the package manager ApplicationPackageManager in a static sStringCache.

While there is a method static void configurationChanged() which clears the cache, it does not seem to get invoked on manual changes. Hence the decribed problem with the wrongly localized activity title after the first invocation.

The solution to this is made possible using reflection to load the class and invoke the method oneself. This is kinda dirty since it is accessing a private method, but it works.

// as before
Configuration config = new Configuration();
Locale.setDefault(mLocale);
config.setLocale(mLocale);

Resources resources = context.getResources();
resources.updateConfiguration(config, resources.getDisplayMetrics());

// CLEAR the cache!
Method method = getClass().getClassLoader()
        .loadClass("android.app.ApplicationPackageManager")
        .getDeclaredMethod("configurationChanged");
method.setAccessible(true);
method.invoke(null);

Alternatively you can use public methods on another non-public API which in turn will also invoke the above method. Still dirty but not invoking private methods.

It seems like you can omit resources.updateConfiguration(...); by using this method though since it will also take care of that.

// Clear the cache. 
Object thread = getClass().getClassLoader()
        .loadClass("android.app.ActivityThread")
        .getMethod("currentActivityThread")
        .invoke(null);
Method method = getClass().getClassLoader()
        .loadClass("android.app.ActivityThread")
        .getMethod("applyConfigurationToResources", Configuration.class);
method.invoke(thread, config);
Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..