做一个推送片段动画 [英] Doing a push fragment animation

查看:30
本文介绍了做一个推送片段动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何做一个动画,通过下一个片段推动当前片段

How can I do a animation that pushes the current fragment by the next fragment

这是我想要的动画:

我当前的动画代码只是将第一个片段与第二个片段重叠,它没有像图片中那样推动它

My current animation code just overlaps the first fragment by the second fragment it didnt push it just like in the picture

代码如下:

result_list.setOnItemClickListener(new OnItemClickListener(){

            @Override
            public void onItemClick(AdapterView<?> av, final View view,
                     final int i, long i2) {
                result_list.setEnabled(false);
                view.animate().setDuration(300).translationX(widthListView).alpha(0).
                withEndAction(new Runnable() {
                    @Override
                    public void run() {
                        //setResult(Activity.RESULT_OK,new Intent().putExtra("bussStopCode", data.get(i).getStopCode()).putExtra("bussStopName", data.get(i).getStopName()));
                        ////int get 1
                        //data.remove(i);

                        int temporaryInteger = i;
                        listLastPostion = temporaryInteger;
                        //customAdapter.notifyDataSetChanged();
                        //view.setTranslationX(0);

                        Log.d("data",conreq.getCollectedData().getBusRouteSetData().get(temporaryInteger - 1).getRouteHeading());
                        Bundle bundle = new Bundle();
                        bundle.putString("busdestination", conreq.getCollectedData().getBusRouteSetData().get(temporaryInteger-1).getRouteHeading());
                        bundle.putString("busnumber", conreq.getCollectedData().getBusRouteSetData().get(temporaryInteger-1).getRouteNo());
                        Fragment fragment = new FragmentNextTripForStop();
                        fragment.setArguments(bundle);
                        FragmentTransaction fragmentManager = getFragmentManager().beginTransaction();
                        fragmentManager.setCustomAnimations(R.anim.right_left_anim_x_left,R.anim.right_left_anim_x_right,R.anim.left_right_anim_x_left,R.anim.left_right_anim_x_right);
                        fragmentManager.add(R.id.fragment_searched_data_xml, fragment).addToBackStack(null).commit();
                       // finish();
                        //overridePendingTransition(R.anim.right_left_anim_x_left,R.anim.right_left_anim_x_right);

                    }
                }); 
            }});

推荐答案

尽管这个问题是重复的,但针对该问题提供的答案对许多观众来说并不适用,并且要求他们对自己的结局做出一些假设.

Although this question is a duplicate, the answer that was provided on that question does not work for many viewers and requires them to make a few assumptions on their end.

考虑到此功能存在于许多应用程序中,这是一个很好的问题,但是它需要一个非常详细的答案.我将尝试将答案分解为一系列分隔的步骤,以确保它是可重复的!

This is an excellent question considering this functionality exists in many applications, however it requires a very elaborate answer. I will try to break the answer down into a series of compartmentalized steps to ensure that it is repeatable!

阻碍我们大多数人轻松做到这一点的问题是一种复合性质.为了完全理解这个问题,让我列出问题:

The problem inhibiting most of us from doing this easily is one of a compound nature. To fully understand this problem, let me list the issues:

  • 我们不应该使用典型的动画框架,因为 FragmentManagerFragmentTransaction 类提供了一个方便的方法,setCustomAnimations(int, int, int int),需要 ObjectAnimators
  • 此外,我们不能在 ObjectAnimators(传统方法)中使用百分比标记
  • 最后,我们只能在运行时确定屏幕宽度,因此必须在我们自己的布局中具有自定义功能
  • We should not use typical animation frameworks as the FragmentManager and FragmentTransaction classes provide a convenience method, setCustomAnimations(int, int, int int), that require ObjectAnimators
  • Further, we cannot use percentage markers in ObjectAnimators (the traditional approach)
  • Finally, we can only determine the screen width at runtime, therefore must have custom functionality in our own layout

为了解决这个问题并提供所需的沉浸式体验,我们必须从多个角度解决它.接下来的几个步骤准确地解释了如何获得此功能!

In order to tackle this problem and provide the immersive experience desired, we must tackle the it from many angles. These next few steps explain exactly how to acquire this functionality!

  1. 我们首先需要为每个 Fragment 定义一个自定义布局,因为我们必须在运行时访问屏幕的宽度,以及一个独立的方法来操作 x 位置基于此宽度的 View(布局).

  1. We first need to define a custom layout for each Fragment as we must have runtime access to the width of the screen, and a self-contained method to manipulate the x-position of the View (the layout) based on this width.

public class FractionTranslateLinearLayout extends LinearLayout{

    private int screenWidth;
    private float fractionX;

    protected void onSizeChanged(int w, int h, int oldW, int oldh){

        // Assign the actual screen width to our class variable.
        screenWidth = w;            

        super.onSizeChanged(w, h, oldW, oldH);
    }

    public float getFractionX(){

        return fractionX;
    }

    public void setFractionX(float xFraction){

        this.fractionX = xFraction;

        // When we modify the xFraction, we want to adjust the x translation
        // accordingly.  Here, the scale is that if xFraction is -1, then
        // the layout is off screen to the left, if xFraction is 0, then the 
        // layout is exactly on the screen, and if xFraction is 1, then the 
        // layout is completely offscreen to the right.
        setX((screenWidth > 0) ? (xFraction * screenWidth) : 0);
    }
}

  • 现在,由于我们有一个特殊的布局,允许我们根据屏幕的物理宽度进行翻译,我们可以在相关的 Fragment XML 文件中使用它.

  • Now, since we have a special layout that will allow us to translate based on the physical width of the screen, we can use it in the associated Fragment XML files.

    <com.[your_package_here].FractionTranslateLinearLayout
        // Omitted namespace.
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <TextView
            android:id="@+id/text_view_1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="Fragment 1" />
    
    </com.[your_package_here].FractionTranslateLinearLayout>
    

    fragment_2.xml

    <com.[your_package_here].FractionTranslateLinearLayout
        // Omitted namespace.
        android:id="@+id/layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <TextView
            android:id="@+id/text_view_2"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="Fragment 2" />
    
    </com.[your_package_here].FractionTranslateLinearLayout>
    

  • 然后,我们必须创建 Fragment 类,这些类将包含实现转换的逻辑.

  • Then, we must create the Fragment classes that will contain the logic to implement the transitions.

    public class Fragment1 extends Fragment {
    
        public View onCreateView(LayoutInflater inf, ViewGroup vg, Bundle b){
    
            // Simply inflate the View from the .xml file.
            return inf.inflate(R.layout.fragment_1, vg, false);
        }
    }
    

    Fragment2.java

    public class Fragment2 extends Fragment {
    
        public View onCreateView(LayoutInflater inf, ViewGroup vg, Bundle b){
    
            // Simply inflate the View from the .xml file.
            return inf.inflate(R.layout.fragment_2, vg, false);
        }
    
        public void onActivityCreated (Bundle savedInstanceState){
    
            View v = getView();
    
            FractionTranslateLinearLayout layout;
            layout = (FractionTranslateLinearLayout) v.findViewById(R.id.layout);
    
            // Move the entire View off to the right of the screen for now.
            layout.setFractionX(1.0f);               
        }
    }
    

  • 现在让我们创建 objectAnimator .xml 文件,我们将使用这些文件在屏幕上翻译 View.请注意,我们将需要四个这样的文件,因为每个进程(出和入)需要一个,每一侧(左和右)需要一个.

  • Let's now create the objectAnimator .xml files that we will use to translate the Views across the screen. Note that we will need four of these files because we need one for each process (out and in), and one for each side (left and right).

    <objectAnimator
        // Omitted namespace.
        android:valueFrom="0"
        android:valueTo="-1"
        // This String must be the exact name of the class variable.
        android:propertyName="xFraction"
        android:valueType="floatType"
        // Duration in milliseconds.
        android:duration="500"/>
    

    slide_right_out.xml

    <objectAnimator
        // Omitted namespace.
        android:valueFrom="0"
        android:valueTo="1"
        // This String must be the exact name of the class variable.
        android:propertyName="xFraction"
        android:valueType="floatType"
        // Duration in milliseconds.
        android:duration="500"/>
    

    slide_left_in.xml

    <objectAnimator
        // Omitted namespace.
        android:valueFrom="-1"
        android:valueTo="0"
        // This String must be the exact name of the class variable.
        android:propertyName="xFraction"
        android:valueType="floatType"
        // Duration in milliseconds.
        android:duration="500"/>
    

    slide_right_in.xml

    <objectAnimator
        // Omitted namespace.
        android:valueFrom="1"
        android:valueTo="0"
        // This String must be the exact name of the class variable.
        android:propertyName="xFraction"
        android:valueType="floatType"
        // Duration in milliseconds.
        android:duration="500"/>
    

  • 请注意,这些文件夹必须放在项目结构中的res/animator"目录中.

    Note that these folders must be placed in the 'res/animator' directory in your project structure.

    1. 创建容器布局,当我们在它们之间转换时,该布局将容纳每个 Fragment.

    <com.android.FrameLayout
        // Omitted namespace.
        android:id="@+id/main_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    

  • 现在,我们必须创建将所有内容包装在一起的 Activity

    public class Main extends Activity {
    
        private boolean showingFirstFragment;            
    
        public void onCreate(Bundle savedInstanceState){
    
            setContentView(R.layout.main);
    
            FragmentManager manager = getFragmentManager();
    
            FragmentTransaction trans = manager.beginTransaction();
    
            // Keep track of which Fragment we are facing.
            showingFirstFragment = true;
    
            // Add the first Fragment to the container.
            trans.add(R.id.main_container, new Fragment1(), "fragment_1");
    
            trans.commit();
        }
    
        public void onBackPressed(){
    
            // Override the back button functionality to simply switch 
            // Fragments. Note that this would normally be done in a click
            // click listener.
            switchFragments();
        }
    
        private void switchFragments(){
    
            FragmentManager manager = getFragmentManager();
            FragmentTransaction trans = manager.beginTransaction();
    
            // Set the animations that will emulate the functionality you
            // requested.    
            int rightIn = R.animator.slide_right_in;
            int rightOut = R.animator.slide_right_out;
            int leftIn = R.animator.slide_left_in;
            int leftOut = R.animator.slide_left_out;
    
            // Note that we pass in 4 animations here.  Please see the 
            // documentation on this method as it is critical to the 
            // understanding of this solution.
            trans.setCustomAnimations(rightIn, leftOut, leftIn, rightOut);          
    
            if(showingFirstFragment){
    
                int container = R.id.main_container;                
    
                // Show the second Fragment.
                trans.replace(container, new Fragment2(), "fragment_2");
                trans.commit();
    
                showingFirstFragment = false;    
            }
            else{
    
                // Show the first Fragment by popping the back stack!
                manager.popBackStack(null);
    
                showingFirstFragment = true;
            }
        }
    }
    

  • 在这个代码示例中,这个类被大量使用.它的方法对流程的执行至关重要!

    In this code example, this class is used heavily. Its methods are crucial to the execution of the process!

    请注意,我在这里做了一些假设,而且这段代码非常独特:

    Note that I have made a few assumptions here, and that this code is quite unique:

    • 此示例使用原始 Fragment 类,因此除非进行必要的修改,否则无法与支持包一起使用.
    • 此示例要求您使用 Android API 13.0 或更高版本.
    • 此示例的目的是提供信息,并希望能够解释此处涉及的问题.在您自己的编辑器中拼凑代码是您应该自行决定的事情!
    • This example uses the original Fragment class, and thus will not work with the support package unless the necessary modifications are made.
    • This example requires that you are using Android API 13.0 or above.
    • The intent of this example was to be informative and to hopefully explain the issues involved here. Piecing the code together in your own editor is something that you should do at your own discretion!

    希望这里有足够的细节来回答您的问题.如果您需要更多,请告诉我.

    Hopefully there is sufficient detail here to answer your question. Please let me know if you require any more.

    此时,应该有足够的代码来实现您自己的解决方案.我确实在没有使用 Eclipse 编辑器的情况下打字的,所以如果有任何错误,请提前接受我的道歉!

    At this point, there should be enough code to implement your own twist on the solution. I did type this up without the crutch of the Eclipse editor, so if there are any errors, please accept my apologies in advance!

    这篇关于做一个推送片段动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆