Java 如何与 NavigationDrawer 一起滑动 ActionBar

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23783496/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 01:11:48  来源:igfitidea点击:

How to slide the ActionBar along with the NavigationDrawer

javaandroidandroid-actionbarandroid-animationnavigation-drawer

提问by Detoxic-Soul

What I want to do is slide the ActionBaralong with the NavigationDrawerwhen the drawer is opened. I am currently not using any third party libraries and if at all possible I want to keep it that way. All i need is an implementation of method like: getActionBarView.slide(dp);

我想要做的是滑动ActionBar与沿NavigationDrawer抽屉打开时。我目前没有使用任何第三方库,如果可能的话,我想保持这种方式。我所需要的只是一个方法的实现,如:getActionBarView.slide(dp);

This is the code I currently use to create the NavigationDrawer:

这是我目前用来创建的代码NavigationDrawer

mDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) {

    public void onDrawerClosed(View view) {
        invalidateOptionsMenu();

        // calling onPrepareOptionsMenu() to hide action bar icons
    }

    @Override
    public void onDrawerSlide(View drawerView, float slideOffset) {
        if (getDeviceType(getApplicationContext()) == DEVICE_TYPE_PHONE) {
            drawerLayout.setScrimColor(Color.parseColor("#00FFFFFF"));
            float moveFactor = (listView.getWidth() * slideOffset);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                all_menu_container_parent.setTranslationX(moveFactor);
            } else {
                TranslateAnimation anim = new TranslateAnimation(lastTranslate, moveFactor, 0.0f, 0.0f);
                anim.setDuration(0);
                anim.setFillAfter(true);
                all_menu_container_parent.startAnimation(anim);

                lastTranslate = moveFactor;
            }
        }
    }

    public void onDrawerOpened(View drawerView) {
        // calling onPrepareOptionsMenu() to hide action bar icons
    }
};
drawerLayout.setDrawerListener(mDrawerToggle);

But it doesn't do what I want, it produces this:

但它没有做我想要的,它产生了这个:

I am currently stuck with this

我目前坚持这个

What I want to achieve is this:

我想要实现的是:

current screen shot from app

来自应用程序的当前屏幕截图

采纳答案by Xaver Kapeller

PLEASE NOTE:This answer was originally written when Android 4.4 (KitKat) was still pretty new. Since Android 5.0 and especially because of the introduction of the ToolBarthis answer cannot be considered up-to-date anymore! But from a technical perspective and for those of you who want to learn about the inner workings of Android this answer might still hold a lot of value!

请注意:这个答案最初是在 Android 4.4 (KitKat) 还很新的时候写的。从 Android 5.0 开始,特别是由于引入了ToolBar这个答案,不能再认为是最新的了!但是从技术角度来看,对于那些想要了解 Android 内部工作原理的人来说,这个答案可能仍然很有价值!

The NavigationDrawerwas specifically designed to be situated below the ActionBarand there is no way to implement the NavigationDrawerto make the ActionBarmove with it - unless maybe looking for the Viewwhich makes up the ActionBarand animating it alongside the NavigationDrawer, but I would never recommend something like this as it would be difficult and error prone. In my opinion you only have two options:

NavigationDrawer专门设计为位于其下方的ActionBar,有没有办法实现NavigationDrawer,使ActionBar与它的举动-除非也许寻找View它构成了ActionBar和动画它旁边的NavigationDrawer,但我绝不会推荐这样的东西,因为它会困难且容易出错。在我看来,你只有两种选择:

  1. Using a library like the SlidingMenu
  2. Implementing a custom sliding menu
  1. 使用像 SlidingMenu 这样的库
  2. 实现自定义滑动菜单

Since you said that you don't want to use a library implementing a custom sliding menu is your only option, fortunately this is really not that hard once you know how to do it.

既然你说你不想使用实现自定义滑动菜单的库是你唯一的选择,幸运的是,一旦你知道如何去做,这真的不是那么难。



1) Basic Explanation

1) 基本说明

You can move the whole content of the Activity- I mean everything including the ActionBar- by putting a margin or a padding on the Viewwhich makes up the Activity. This Viewis the parent of the Viewwith the id android.R.id.content:

您可以移动的全部内容Activity-我的意思是一切,包括ActionBar-通过把保证金或填充在View其拼成的Activity。这ViewViewid的父级android.R.id.content

View content = (View) activity.findViewById(android.R.id.content).getParent();

On Honeycomb (Android version 3.0 - API level 11) or above - in other words after the ActionBarwas introduced - you need to use margins to change the Activitiesposition and on previous versions you need to use a padding. To simplify this I recommend creating helper methods which perform the correct action for each API level. Let's first look at how to set the position of the Activity:

在 Honeycomb(Android 3.0 版 - API 级别 11)或更高版本上 - 换句话说,在ActionBar引入之后 - 您需要使用边距来更改Activities位置,而在以前的版本中您需要使用填充。为了简化这一点,我建议创建辅助方法,为每个 API 级别执行正确的操作。我们先来看看如何设置 的位置Activity

public void setActivityPosition(int x, int y) {
    // With this if statement we can check if the devices API level is above Honeycomb or below
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        // On Honeycomb or abvoe we set a margin
        FrameLayout.LayoutParams contentParams = (FrameLayout.LayoutParams) this.content.getLayoutParams();
        contentParams.setMargins(x, y, -x, -y);
        this.content.setLayoutParams(contentParams);
    } else {
        // And on devices below Honeycomb we set a padding
        this.content.setPadding(x, y, -x, -y);
    }
}

Notice that in both cases there is either a negative margin or a negative padding on the opposite sides. This is to essentially increase the size of the Activitybeyond its normal bounds. This prevents the actual size of the Activityto change when we slide it somewhere.

请注意,在这两种情况下,两侧都有负边距或负填充。这实质上是增加了Activity超出其正常范围的大小。Activity当我们将它滑动到某个地方时,这可以防止它的实际大小发生变化。

We additionally need two methods to get the current position of the Activity. One for the x position, one for the y position:

我们还需要两种方法来获取Activity. 一个用于 x 位置,一个用于 y 位置:

public int getActivityPositionX() {
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        // On Honeycomb or above we return the left margin
        FrameLayout.LayoutParams contentParams = (FrameLayout.LayoutParams) this.content.getLayoutParams();
        return contentParams.leftMargin;
    } else {
        // On devices below Honeycomb we return the left padding
        return this.content.getPaddingLeft();
    }
}

public int getActivityPositionY() {
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        // On Honeycomb or above we return the top margin
        FrameLayout.LayoutParams contentParams = (FrameLayout.LayoutParams) this.content.getLayoutParams();
        return contentParams.topMargin;
    } else {
        // On devices below Honeycomb we return the top padding
        return this.content.getPaddingTop();
    }
} 

It is also very simple to add animations. The only important thing here is a bit of math to animate it from its previous position to its new position

添加动画也很简单。这里唯一重要的是一些数学运算,可以将它从以前的位置动画到新的位置

// We get the current position of the Activity
final int currentX = getActivityPositionX();
final int currentY = getActivityPositionY();

// The new position is set
setActivityPosition(x, y);

// We animate the Activity to slide from its previous position to its new position
TranslateAnimation animation = new TranslateAnimation(currentX - x, 0, currentY - y, 0);
animation.setDuration(500);
this.content.startAnimation(animation);

You can display a Viewat the location which is revealed by sliding away the Activityby adding it to the parent of the View:

您可以通过将 a 添加到 的父级来将其View滑开,从而在显示的位置显示 a :ActivityView

final int currentX = getActivityPositionX();

FrameLayout menuContainer = new FrameLayout(context);

// The width of the menu is equal to the x position of the `Activity`
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(currentX, ViewGroup.LayoutParams.MATCH_PARENT);
menuContainer.setLayoutParams(params);

ViewGroup parent = (ViewGroup) content.getParent();
parent.addView(menuContainer);

And that is pretty much all you need to create a basic sliding menu that works on most if not all devices above Eclair (Android 2.1 - API level 7).

这几乎是您创建一个基本的滑动菜单所需的全部内容,该菜单适用于 Eclair(Android 2.1 - API 级别 7)以上的大多数设备(如果不是所有设备)。



2) Animating the Activity

2)动画 Activity

The first part of creating a sliding menu is making the Activitymove out of the way. As such we should first try to move the Activityaround like this:
enter image description here

创建滑动菜单的第一部分是Activity让步。因此,我们应该首先尝试Activity像这样移动周围:
在此处输入图片说明

To create this we just have to put the code above together:

要创建它,我们只需要将上面的代码放在一起:

import android.os.Build;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;

public class ActivitySlider {

    private final FragmentActivity activity;
    private final View content;

    public ActivitySlider(FragmentActivity activity) {
        this.activity = activity;

        // Here we get the content View from the Activity.
        this.content = (View) activity.findViewById(android.R.id.content).getParent();
    }

    public void slideTo(int x, int y) {

        // We get the current position of the Activity
        final int currentX = getActivityPositionX();
        final int currentY = getActivityPositionY();

        // The new position is set
        setActivityPosition(x, y);

        // We animate the Activity to slide from its previous position to its new position
        TranslateAnimation animation = new TranslateAnimation(currentX - x, 0, currentY - y, 0);
        animation.setDuration(500);
        this.content.startAnimation(animation);
    }

    public void setActivityPosition(int x, int y) {
        // With this if statement we can check if the devices API level is above Honeycomb or below
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            // On Honeycomb or above we set a margin
            FrameLayout.LayoutParams contentParams = (FrameLayout.LayoutParams) this.content.getLayoutParams();
            contentParams.setMargins(x, y, -x, -y);
            this.content.setLayoutParams(contentParams);
        } else {
            // And on devices below Honeycomb we set a padding
            this.content.setPadding(x, y, -x, -y);
        }
    }

    public int getActivityPositionX() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            // On Honeycomb or above we return the left margin
            FrameLayout.LayoutParams contentParams = (FrameLayout.LayoutParams) this.content.getLayoutParams();
            return contentParams.leftMargin;
        } else {
            // On devices below Honeycomb we return the left padding
            return this.content.getPaddingLeft();
        }
    }

    public int getActivityPositionY() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            // On Honeycomb or above we return the top margin
            FrameLayout.LayoutParams contentParams = (FrameLayout.LayoutParams) this.content.getLayoutParams();
            return contentParams.topMargin;
        } else {
            // On devices below Honeycomb we return the top padding
            return this.content.getPaddingTop();
        }
    }
}

You can use the ActivitySliderclass like this:

你可以ActivitySlider像这样使用这个类:

ActivitySlider slider = new ActivitySlider(activity);

// This would move the Activity 400 pixel to the right and 100 pixel down
slider.slideTo(400, 100);


3) Adding the sliding menu

3) 添加滑动菜单

Now we want to reveal a menu when the Activitymoves out of the way like this: enter image description here
As you can see it also pushes the ActionBarto the side.

现在我们想要在Activity移开时显示一个菜单,如下所示: 在此处输入图片说明
正如您所看到的,它也将 推ActionBar到了一边。

The ActivitySliderclass does not need to be modified that much to create a sliding menu, basically we just add two methods, showMenu()and hideMenu(). I will stick to best practices and use a Fragmentas the sliding menu. The first thing we need need is a View- for example a FrameLayout- as a container for our Fragment. We need to add this Viewto the parent of the Viewof the Activity:

这个ActivitySlider类不需要修改那么多来创建一个滑动菜单,基本上我们只需要添加两个方法,showMenu()hideMenu(). 我将坚持最佳实践并使用 aFragment作为滑动菜单。我们需要的第一件事是一个View——例如一个FrameLayout——作为我们的Fragment. 我们需要把它添加View到的父ViewActivity

// We get the View of the Activity
View content = (View) activity.findViewById(android.R.id.content).getParent();

// And its parent
ViewGroup parent = (ViewGroup)  content.getParent();

// The container for the menu Fragment is a FrameLayout
// We set an id so we can perform FragmentTransactions later on
FrameLayout menuContainer = new FrameLayout(this.activity);
menuContainer.setId(R.id.flMenuContainer);

// The visibility is set to GONE because the menu is initially hidden
menuContainer.setVisibility(View.GONE);

// The container for the menu Fragment is added to the parent
parent.addView(menuContainer);

Since we set the visibility of the container Viewto VISIBLE only when the sliding menu is actually open we can use the following method to check if the menu is open or closed:

由于我们View仅在滑动菜单实际打开时才将容器的可见性设置为可见,因此我们可以使用以下方法检查菜单是打开还是关闭:

public boolean isMenuVisible() {
    return this.menuContainer.getVisibility() == View.VISIBLE;
}

To set the menu Fragmentwe add a setter method that performs a FragmentTransactionand adds the menu Fragmentto the FrameLayout:

要设置菜单Fragment,我们添加一个setter方法执行一个FragmentTransaction并添加菜单FragmentFrameLayout

public void setMenuFragment(Fragment fragment) {
    FragmentManager manager = this.activity.getSupportFragmentManager();
    FragmentTransaction transaction = manager.beginTransaction();
    transaction.replace(R.id.flMenuContainer, fragment);
    transaction.commit();
}

I also tend to add a second setter which instantiates the Fragmentfrom a Classfor convenience:

为了方便起见,我还倾向于添加第二个 setter 来实例化Fragmentfrom a Class

public <T extends Fragment> void setMenuFragment(Class<T> cls) {
    Fragment fragment = Fragment.instantiate(this.activity, cls.getName());
    setMenuFragment(fragment);
}

There is one additional important thing to consider when it comes to the menu Fragment. We are operating much further up in the Viewhierarchy than normally. As such we have to take things like the height of the status bar into account. If we didn't account for this the top of the menu Fragmentwould we be hidden behind the status bar. You can get the height of the status bar like this:

关于菜单,还有一件重要的事情需要考虑Fragment。我们在View层次结构中的运作比平时要高得多。因此,我们必须考虑状态栏的高度等因素。如果我们没有考虑到这一点,菜单顶部Fragment就会隐藏在状态栏后面。您可以像这样获取状态栏的高度:

Rect rectangle = new Rect();
Window window = this.activity.getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rectangle);
final int statusBarHeight = rectangle.top;

We have to put a top margin on the container Viewof the menu Fragmentlike this:

我们必须像这样View在菜单的容器上放置一个上边距Fragment

// These are the LayoutParams for the menu Fragment
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(width, ViewGroup.LayoutParams.MATCH_PARENT);

// We put a top margin on the menu Fragment container which is equal to the status bar height
params.setMargins(0, statusBarHeight, 0, 0);
menuContainer.setLayoutParams(fragmentParams);

Finally we can put all this together:

最后我们可以把所有这些放在一起:

import android.graphics.Rect;
import android.os.Build;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
import at.test.app.R;
import at.test.app.helper.LayoutHelper;

public class ActivitySlider {

    private final FragmentActivity activity;
    private final View content;
    private final FrameLayout menuContainer;

    public ActivitySlider(FragmentActivity activity) {
        this.activity = activity;

        // We get the View of the Activity
        this.content = (View) activity.findViewById(android.R.id.content).getParent();

        // And its parent
        ViewGroup parent = (ViewGroup) this.content.getParent();

        // The container for the menu Fragment is added to the parent. We set an id so we can perform FragmentTransactions later on
        this.menuContainer = new FrameLayout(this.activity);
        this.menuContainer.setId(R.id.flMenuContainer);

        // We set visibility to GONE because the menu is initially hidden
        this.menuContainer.setVisibility(View.GONE);
        parent.addView(this.menuContainer);
    }

    public <T extends Fragment> void setMenuFragment(Class<T> cls) {
        Fragment fragment = Fragment.instantiate(this.activity, cls.getName());
        setMenuFragment(fragment);
    }

    public void setMenuFragment(Fragment fragment) {
        FragmentManager manager = this.activity.getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.replace(R.id.flMenuContainer, fragment);
        transaction.commit();
    }

    public boolean isMenuVisible() {
        return this.menuContainer.getVisibility() == View.VISIBLE;
    }

    // We pass the width of the menu in dip to showMenu()
    public void showMenu(int dpWidth) {

        // We convert the width from dip into pixels
        final int menuWidth = LayoutHelper.dpToPixel(this.activity, dpWidth);

        // We move the Activity out of the way
        slideTo(menuWidth, 0);

        // We have to take the height of the status bar at the top into account!
        Rect rectangle = new Rect();
        Window window = this.activity.getWindow();
        window.getDecorView().getWindowVisibleDisplayFrame(rectangle);
        final int statusBarHeight = rectangle.top;

        // These are the LayoutParams for the menu Fragment
        FrameLayout.LayoutParams fragmentParams = new FrameLayout.LayoutParams(menuWidth, ViewGroup.LayoutParams.MATCH_PARENT);

        // We put a top margin on the menu Fragment container which is equal to the status bar height
        fragmentParams.setMargins(0, statusBarHeight, 0, 0);
        this.menuContainer.setLayoutParams(fragmentParams);

        // Perform the animation only if the menu is not visible
        if(!isMenuVisible()) {

            // Visibility of the menu container View is set to VISIBLE
            this.menuContainer.setVisibility(View.VISIBLE);

            // The menu slides in from the right
            TranslateAnimation animation = new TranslateAnimation(-menuWidth, 0, 0, 0);
            animation.setDuration(500);
            this.menuContainer.startAnimation(animation);
        }
    }

    public void hideMenu() {

        // We can only hide the menu if it is visible
        if(isMenuVisible()) {

            // We slide the Activity back to its original position
            slideTo(0, 0);

            // We need the width of the menu to properly animate it
            final int menuWidth = this.menuContainer.getWidth();

            // Now we need an extra animation for the menu fragment container
            TranslateAnimation menuAnimation = new TranslateAnimation(0, -menuWidth, 0, 0);
            menuAnimation.setDuration(500);
            menuAnimation.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {

                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    // As soon as the hide animation is finished we set the visibility of the fragment container back to GONE
                    menuContainer.setVisibility(View.GONE);
                }

                @Override
                public void onAnimationRepeat(Animation animation) {

                }
            });
            this.menuContainer.startAnimation(menuAnimation);
        }
    }

    public void slideTo(int x, int y) {

        // We get the current position of the Activity
        final int currentX = getActivityPositionX();
        final int currentY = getActivityPositionY();

        // The new position is set
        setActivityPosition(x, y);

        // We animate the Activity to slide from its previous position to its new position
        TranslateAnimation animation = new TranslateAnimation(currentX - x, 0, currentY - y, 0);
        animation.setDuration(500);
        this.content.startAnimation(animation);
    }

    public void setActivityPosition(int x, int y) {
        // With this if statement we can check if the devices API level is above Honeycomb or below
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            // On Honeycomb or above we set a margin
            FrameLayout.LayoutParams contentParams = (FrameLayout.LayoutParams) this.content.getLayoutParams();
            contentParams.setMargins(x, y, -x, -y);
            this.content.setLayoutParams(contentParams);
        } else {
            // And on devices below Honeycomb we set a padding
            this.content.setPadding(x, y, -x, -y);
        }
    }

    public int getActivityPositionX() {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            // On Honeycomb or above we return the left margin
            FrameLayout.LayoutParams contentParams = (FrameLayout.LayoutParams) this.content.getLayoutParams();
            return contentParams.leftMargin;
        } else {
            // On devices below Honeycomb we return the left padding
            return this.content.getPaddingLeft();
        }
    }

    public int getActivityPositionY() {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            // On Honeycomb or above we return the top margin
            FrameLayout.LayoutParams contentParams = (FrameLayout.LayoutParams) this.content.getLayoutParams();
            return contentParams.topMargin;
        } else {
            // On devices below Honeycomb we return the top padding
            return this.content.getPaddingTop();
        }
    }
}

I use a static helper method in showMenu()to convert dip to pixels. Here is the code of this method:

我使用静态辅助方法showMenu()将倾角转换为像素。下面是这个方法的代码:

public static int dpToPixel(Context context, int dp) {
    float scale = getDisplayDensityFactor(context);
    return (int) (dp * scale + 0.5f);
}

private static float getDisplayDensityFactor(Context context) {
    if (context != null) {
        Resources res = context.getResources();
        if (res != null) {
            DisplayMetrics metrics = res.getDisplayMetrics();
            if(metrics != null) {
                return metrics.density;
            }
        }
    }
    return 1.0f;
}

You can use this new version of the ActivitySliderclass like this:

您可以ActivitySlider像这样使用这个新版本的类:

ActivitySlider slider = new ActivitySlider(activity);
slider.setMenuFragment(MenuFragment.class);

// The menu is shown with a width of 200 dip
slider.showMenu(200);

...

// Hide the menu again
slider.hideMenu();


4) Conclusion & Testing

4) 结论与测试

Doing something like this is surprisingly easy when you know that you can simply put a margin or a padding on the Viewof the Activity. But the difficulty is in making it work on a lot of different devices. Implementations can change a lot across multiple API Levels and that can have considerable influence on how this behaves. Having said that any code I posted here should work on most if not all devices above Eclair (Android 2.1 - API level 7) without any problems.
Of course the solution I posted here is not complete, it could use a little extra polishing and cleaning up, so feel free to improve the code to suit your needs!

当您知道可以简单地ViewActivity. 但困难在于让它在许多不同的设备上工作。实现可以跨多个 API 级别发生很大变化,这可能对其行为方式产生相当大的影响。话虽如此,我在这里发布的任何代码都应该在 Eclair(Android 2.1 - API 级别 7)以上的大多数设备上运行,没有任何问题。
当然,我在这里发布的解决方案并不完整,它可以使用一些额外的抛光和清理,因此请随时改进代码以满足您的需求!

I have tested everything on the following devices:

我已经在以下设备上测试了所有内容:

HTC

  • One M8 (Android 4.4.2 - KitKat):Working
  • Sensation (Android 4.0.3 - Ice Cream Sandwich):Working
  • Desire (Android 2.3.3 - Gingerbread):Working
  • One (Android 4.4.2 - KitKat):Working

Samsung

  • Galaxy S3 Mini (Android 4.1.2 - Jelly Bean):Working
  • Galaxy S4 Mini (Android 4.2.2 - Jelly Bean):Working
  • Galaxy S4 (Android 4.4.2 - KitKat):Working
  • Galaxy S5 (Android 4.4.2 - KitKat):Working
  • Galaxy S Plus (Android 2.3.3 - Gingerbread):Working
  • Galaxy Ace (Android 2.3.6 - Gingerbread):Working
  • Galaxy S2 (Android 4.1.2 - Jelly Bean):Working
  • Galaxy S3 (Android 4.3 - Jelly Bean):Working
  • Galaxy Note 2 (Android 4.3 - Jelly Bean):Working
  • Galaxy Nexus (Android 4.2.1 - Jelly Bean):Working

Motorola

  • Moto G (Android 4.4.2 - KitKat):Working

LG

  • Nexus 5 (Android 4.4.2 - KitKat):Working

ZTE

  • Blade (Android 2.1 - Eclair):Working

宏达电

  • 一台 M8(Android 4.4.2 - KitKat):工作
  • Sensation (Android 4.0.3 - Ice Cream Sandwich):工作
  • 欲望(Android 2.3.3 - Gingerbread):工作
  • 一(Android 4.4.2 - KitKat):工作

三星

  • Galaxy S3 Mini(Android 4.1.2 - Jelly Bean):工作
  • Galaxy S4 Mini(Android 4.2.2 - Jelly Bean):工作
  • Galaxy S4(Android 4.4.2 - KitKat):工作
  • Galaxy S5(Android 4.4.2 - KitKat):工作
  • Galaxy S Plus(Android 2.3.3 - Gingerbread):工作
  • Galaxy Ace(Android 2.3.6 - Gingerbread):工作
  • Galaxy S2(Android 4.1.2 - Jelly Bean):工作
  • Galaxy S3(Android 4.3 - Jelly Bean):工作
  • Galaxy Note 2(Android 4.3 - Jelly Bean):工作正常
  • Galaxy Nexus(Android 4.2.1 - Jelly Bean):工作

摩托罗拉

  • Moto G(Android 4.4.2 - KitKat):工作

LG

  • Nexus 5(Android 4.4.2 - KitKat):工作

中兴通讯

  • Blade(Android 2.1 - Eclair):工作

I hope I could help you and if you have any further questions or anything else is unclear please feel free to ask!

希望能帮到你,如果还有什么不懂的,或者有什么不明白的,欢迎追问!