ObjectAnimator onAnimationEnd 监听器在动画完成之前被调用

问题描述 投票:0回答:1

这很奇怪,但似乎当我将 AnimatorListener 附加到用于动画片段事务的 ObjectAnimator 时,回调实际上会在动画完成之前稍微调用。 我使用侦听器将内容填充到片段中(来自数据库)。该操作有时可能需要相当长的时间(~200ms),当我在 onCreate 左右执行此操作时,它只会破坏动画,因为内容是在动画期间返回并渲染的......然后有很多垃圾和口吃。 。 因此,当我将填充调用添加到侦听器中时,当数据库选择也需要很长时间时它就会起作用。但有时它几乎是瞬时的,在这种情况下,当在动画结束之前调用回调时,我会遇到问题。回调和实际结束之间的间隙足够长,足以从数据库返回数据并再次破坏动画的流畅性:/

你们知道如何解决这个问题吗?下面是该片段的几乎完整代码。

所以基本上有两种方法可以解决这个问题。我可以找到完全另一种解决方案,如何将内容填充到片段中而没有垃圾动画,或者我可以找到一种方法来解决侦听器的问题。

还有一种我不喜欢的额外方式。我可以创建一个处理程序并调用 postDelayed.. 糟糕的解决方案:)

public class ImportantContactsFragment extends Fragment {

public static final String TAG = ImportantContactsFragment.class.getSimpleName();


private ListView list;
private Spinner departmentsSwitcher;
private Spinner facultiesSwitcher;
private ContactsAdapter adapter;
private ArrayList<ImportantContact> currentListOfPeople;
private int currentFaculty = 1;
private Department currentDeparment = Department.STUDY_DEPARTMENT;
private PullToRefreshAttacher mPullToRefreshAttacher;
private boolean boot = true;
private AsyncTask<Integer, ArrayList<ImportantContact>, ArrayList<ImportantContact>> task;


private ArrayList<Faculty> faculties;


private SpinnerAdapter departmentsSpinnerAdapter;
private SpinnerAdapter facultiesSpinnerAdapter;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    currentListOfPeople = new ArrayList<ImportantContact>();
    faculties = new ArrayList<Faculty>(2);
    currentDeparment = Department.STUDY_DEPARTMENT;

    faculties.add(Faculty.getFEL());
    faculties.add(Faculty.getFIT());

    FrameLayout view = (FrameLayout) inflater.inflate(R.layout.important_contacts_fragment_list_layout, container, false);
    departmentsSwitcher = (Spinner) view.findViewById(R.id.departmentsSpinner);
    facultiesSwitcher = (Spinner) view.findViewById(R.id.facultiesSpinner);


    facultiesSpinnerAdapter = new ArrayAdapter<Faculty>(getActivity(), R.layout.spinner_text_view, faculties);
    departmentsSpinnerAdapter = new ArrayAdapter<Department>(getActivity(), R.layout.spinner_text_view, Department.values());


    departmentsSwitcher.setAdapter(departmentsSpinnerAdapter);
    facultiesSwitcher.setAdapter(facultiesSpinnerAdapter);

    list = (ListView) view.findViewById(R.id.list);
    adapter = new ContactsAdapter(getActivity(), R.layout.important_contacts_list_item, currentListOfPeople, list);
    list.setAdapter(adapter);
    list.requestFocus();
    departmentsSwitcher.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            currentDeparment = (Department) departmentsSpinnerAdapter.getItem(position);
            fillAdapterWithData(currentFaculty, currentDeparment);
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
        }
    });
    facultiesSwitcher.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            currentFaculty = position + 1;
            fillAdapterWithData(currentFaculty, currentDeparment);
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    });

    return view;
}


@Override
public void onResume() {
    super.onResume();
    Tracking.onResume(this);
//        fillAdapterWithData(currentFaculty, currentDeparment);

}

@Override
public void onPause() {
    super.onPause();
    if (task != null) {
        task.cancel(true);
    }
}


@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);




}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    getActivity().getActionBar().setTitle(getString(R.string.important_contacts));
}

public void fillAdapterWithData(int facultyId, Department department) {
    if (boot) {
        boot = false;
        return;
    }
    currentListOfPeople.clear();
    if (task != null) {
        task.cancel(true);
    }
    task = new AsyncTask<Integer, ArrayList<ImportantContact>, ArrayList<ImportantContact>>() {
        @Override
        protected ArrayList<ImportantContact> doInBackground(Integer... params) {
            return Controller.peopleDBController.getListOfImportantContactFromListOfContact(Controller.contactsDBController.searchRows(params[0], params[1]));
        }


        @Override
        protected void onPostExecute(ArrayList<ImportantContact> importantContacts) {

//          adapter.notifyDataSetChanged();
            adapter.addAll(importantContacts);


        }
    };
//        getActivity().setProgressBarVisibility(true);

    task.execute(facultyId, department.ordinal());
    adapter.addAll(Controller.peopleDBController.getListOfImportantContactFromListOfContact(Controller.contactsDBController.searchRows(facultyId, department.ordinal())));

}

@Override
public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) {
    if(enter){
        Animator animator = AnimatorInflater.loadAnimator(getActivity(), R.anim.fragment_slide_anim);
        if(animator!=null){
        animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
//                    fillAdapterWithData(currentFaculty, currentDeparment);
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        }
        return  animator;
    }
    else{
        return super.onCreateAnimator(transit, enter, nextAnim);
    }



}
android animation android-fragments android-asynctask objectanimator
1个回答
0
投票

有几种方法可以处理这个计时问题,让动画回调稍微提前完成:

  1. 在加载数据之前添加一点延迟

您可以使用 Handler 来延迟加载数据,延迟时间非常小,例如 50-100 毫秒。这将确保动画完全完成:

animator.addListener(new AnimatorListenerAdapter() {

  @Override
  public void onAnimationEnd(Animator animation) {

    Handler().postDelayed(() -> {
      // load data
    }, 100);

  }

});
  1. 使用 animator.end() 回调代替

Animator 类有一个 end() 回调,用于传递动画的实际结束时间。您可以使用它代替侦听器来加载数据:

animator.end(() -> {
  // load data
});
  1. 延长动画持续时间

使动画稍微长一些,以考虑到早期发生的回调。例如,如果提前 50ms 结束,则将持续时间延长 50ms。

  1. 在下一帧加载数据

使用View.post()加载动画后下一帧的数据:

animator.addListener(new AnimatorListenerAdapter() {

  @Override 
  public void onAnimationEnd(Animator animation) {
    view.post(() -> {
      // load data
    });
  }

});

总的来说,最简单的选项可能是使用小的延迟或 end() 回调。

© www.soinside.com 2019 - 2024. All rights reserved.