19
votes

I'm implementing a visual design for an app, and it turns out that the Galaxy S4 misaligns the actionbar home icon, as demonstrated in the screenshot:

enter image description here

The screenshots were taken using the exact same APK file on both devices. The purple guideline sits at 16dp from the left, and it is quite important to the rest of the screen layout. The S4 adds another 8dp or so. This extra margin makes the home icon really look out of place.

I've tried a bunch of other Samsung phones at different resolutions/densities (Galaxy S3, Galaxy S4 Mini, Galaxy Ace) and these all align the icon correctly at 16dp.

I'd chalk it up to Android fragmentation and move on, but the marketshare of the Galaxy S4 is so big that I can't really ignore the issue. Has anyone else encountered this, and found a fix?

1
Confirmed the same issue on Galaxy S3 with the 4.4.2 update. Really really annoying. - Guzba
It could be a problem with your styles, the ActionBar can sometimes be a little tricky in that regard, but most likely Samsung just messed the ActionBar up. First I would test if a negative margin fixes the problem. - Xaver Kapeller
Sherlock delegates to the "native" actionbar if the OS version has one. - Barend
Just a thought: if anyone's got a rooted S3/S4, perhaps comparing view hierarchies may give some insight. I.e. are there any differences in the hierarchies? If not, how about the various view property values etc? ALternatively, it may be interesting to determine whether custom ROMs suffer the same issue? - MH.
I don't get why everyone is commenting this does not occur on their S4. I was really hoping on finding a sollution to this, but I see that every single app on the S4 does this. I have a Moto G, Nexus 7 and S4 in front of me, only the S4 screws up. I guess I'll have to keep it like that. - Mathijs Segers

1 Answers

2
votes

This code is pretty self-explanatory. It first checks if the current device is a Samsung Galaxy S4 model, based on the list found here. If it is, it then looks for the relevant Views based on the ActionBar's layout and the home ImageView's relative position in the hierarchy. It then shifts them left by the (positive) offset parameter. It also checks if a Custom View is displayed, and shifts that as well. The only change is to the Views' x coordinates, so it should work with any theme or style.

private static final String SAMSUNG = "SAMSUNG";
private static final String[] S4_MODELS = {
    "GT-I9506", "GT-I9505G", "SGH-I337", "SGH-M919",
    "SCH-I545", "SPH-L720", "SCH-R970", "GT-I9508",
    "SCH-I959", "GT-I9502", "SGH-N045", "SGH-I337M",
    "SGH-M919V", "SCH-R970X", "SCH-R970C"
};

private void adjustGalaxyS4(int offset)
{
    if (isGalaxyS4())
        shiftHomeView(offset);
}

private boolean isGalaxyS4()
{
    String manufacturer = Build.MANUFACTURER.toUpperCase();
    String model = Build.MODEL.toUpperCase();

    if (SAMSUNG.equals(manufacturer) && !TextUtils.isEmpty(model))
    {
        for (String m : S4_MODELS)
            if (model.contains(m))
                return true;
    }

    return false;
}

private void shiftHomeView(float offset)
{
    try
    {
        View grandParentView = (View) ((View) findViewById(android.R.id.home).getParent()).getParent();
        View upView = ((ViewGroup) ((ViewGroup) grandParentView).getChildAt(0)).getChildAt(0);

        grandParentView.setX(grandParentView.getX() - offset);
        upView.setX(upView.getX() + offset);

        if ((getActionBar().getDisplayOptions() & ActionBar.DISPLAY_SHOW_CUSTOM) != 0)  
            getActionBar().getCustomView().setX(getActionBar().getCustomView().getX() - offset);
    }
    catch (Exception e)
    {
        // Fail silently
    }
}