Выполнение анимации фрагментации фрагмента

Как я могу сделать анимацию, которая подталкивает текущий фрагмент следующим фрагментом

Вот анимация, которую я хочу: enter image description here

Мой текущий код анимации просто перекрывает первый фрагмент вторым фрагментом, который он не нажимал на него, как на картинке

Вот код:

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);

                    }
                }); 
            }});

Ответ 1

Хотя этот вопрос является дубликатом, ответ, который был предоставлен по этому вопросу, не работает для многих зрителей и требует от них сделать несколько предположений на их конце.

Это отличный вопрос, учитывая, что эта функциональность существует в приложениях много, однако для этого требуется очень сложный ответ. Я попытаюсь разбить ответ на несколько разделенных шагов, чтобы обеспечить его повторяемость!

Проблема

Проблема, препятствующая большинству из нас легко сделать это, является сложной. Чтобы полностью понять эту проблему, позвольте мне перечислить проблемы:

  • Мы не должны использовать обычные рамки анимации, поскольку классы FragmentManager и FragmentTransaction предоставляют удобный метод setCustomAnimations(int, int, int int), для которого требуется ObjectAnimators
  • Кроме того, мы не можем использовать процентные маркеры в ObjectAnimators (традиционный подход)
  • Наконец, мы можем определить ширину экрана во время выполнения, поэтому должны иметь пользовательские функции в нашем собственном макете

Решение

Чтобы решить эту проблему и обеспечить желаемый опыт, мы должны решить ее с разных точек зрения. Следующие несколько шагов объясняют, как получить эту функциональность!

  • Сначала нам нужно определить настраиваемый макет для каждого Fragment, так как мы должны иметь доступ к ширине экрана во время выполнения и автономный метод управления x-позицией View ( макет) на основе этой ширины.

    FractionTranslateLinearLayout.java

    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);
        }
    }
    
  • Теперь, поскольку у нас есть специальный макет, который позволит нам переводить на основе физической ширины экрана, мы можем использовать его в связанных XML файлах фрагмента.

    fragment_1.xml

    <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, которые будут содержать логику для реализации переходов.

    Fragment1.java

    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 по экрану. Обратите внимание, что нам понадобятся четыре из этих файлов, потому что нам нужен один для каждого процесса (вне и внутри) и один для каждой стороны (слева и справа).

    slide_left_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_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" в вашей структуре проекта.

  • Создайте макет контейнера, который будет удерживать каждый Fragment при переходе между ними.

    main.xml

    <com.android.FrameLayout
        // Omitted namespace.
        android:id="@+id/main_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    
  • Теперь мы должны создать Activity, который обернет все вместе!

    Main.java

    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;
            }
        }
    }
    

В этом примере кода используется этот класс. Его методы имеют решающее значение для выполнения процесса!

Некоторые соображения

Обратите внимание, что здесь я сделал несколько предположений и что этот код совершенно уникален:

  • В этом примере используется исходный класс Fragment и, следовательно, не будет работать с пакетом поддержки, если не будут сделаны необходимые изменения.
  • В этом примере требуется, чтобы вы использовали Android API 13.0 или выше.
  • Цель этого примера состояла в том, чтобы быть информативным и, надеюсь, объяснить возникшие здесь проблемы. Создание кода в собственном редакторе - это то, что вы должны делать по своему усмотрению!

Надеюсь, здесь достаточно подробностей, чтобы ответить на ваш вопрос. Пожалуйста, дайте мне знать, если вам потребуется больше.

В этот момент должно быть достаточно кода для реализации вашего собственного поворота в решении. Я напечатал это без костыля редактора Eclipse, поэтому, если есть какие-либо ошибки, пожалуйста, примите мои извинения заранее!