FragmentTransaction动画工作,但似乎出问题(FragmentTransaction

2019-10-20 12:36发布

我设法得到碎片在我的应用程序,因为我想他们,但是,也有一些是与动画不符正确地移动。

更具体地:我有2帧,以及3个片段的活性。 两个是固定的,并且从所述第三从左向右移动,覆盖和不覆盖所述第一2。

当移动片段移动时,它暂时出现在其最终位置滑动,因为它应该从开始到结束(使用动画资源slide_in_left,slide_in_right,slide_out_left和slide_out_right)之前。

编辑:我的测试设备是第二代的Nexus 7和三星galaxy S3,所以它不应该是硬件问题。 仿真器跳过太多帧注意到它。

如果我将所有3个片段在一起不会发生这种情况。

我做了一个简单的应用程序来演示这个问题,也许有人可以解决一些启发。 下面是相关的文件:

MainActivity.java

public class MainActivity extends Activity {

    MainFragment mFragment1;
    MainFragment mFragment2;
    MainFragment mFragment3;
    // variable to hold current frame for mFragment2
    int mFrag2Frame;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState != null) {
            mFrag2Frame = savedInstanceState.getInt("frag_2_frame");
        } else {
            mFrag2Frame = R.id.rightFrame;
        }
        // First add mFragment1 and mFragment3 where they will stay.
        // Then add mFragment2 over the top of its current frame
        FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.add(R.id.leftFrame, mFragment1 = MainFragment.Frag1())
                .add(R.id.rightFrame, mFragment3 = MainFragment.Frag3())
                .add(mFrag2Frame, mFragment2 = MainFragment.Frag2())
                .commit();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putInt("frag_2_frame", mFrag2Frame);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();
        if (id == R.id.action_slide) {
            slide();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    public void slide() {

        boolean isLeft = mFrag2Frame == R.id.leftFrame;
        FragmentTransaction ft = getFragmentManager().beginTransaction();

        // set animations according to current position of mFragment2
        ft.setCustomAnimations(isLeft ? R.anim.slide_in_left : R.anim.slide_in_right,
                isLeft ? R.anim.slide_out_right : R.anim.slide_out_left);

        // change mFrag2Frame according to its current value
        mFrag2Frame = isLeft ? R.id.rightFrame : R.id.leftFrame;

        ft.remove(mFragment2)
                .add(mFrag2Frame, mFragment2 = MainFragment.Frag2())
                .commit();
    }
}

main.xml中

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.slidingpanels.MainActivity" >

    <FrameLayout
        android:id="@+id/leftFrame"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" >

    </FrameLayout>

    <FrameLayout
        android:id="@+id/rightFrame"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" >

    </FrameLayout>

</LinearLayout>

MainFragment.java

public class MainFragment extends Fragment {

    int mResourceId = R.layout.frag;
    int mColour;

    public MainFragment() {
    }

    private MainFragment(int colour) {
        mColour = colour;
    }

    public static MainFragment Frag1() {
        return new MainFragment(Color.RED);
    }
    public static MainFragment Frag2() {
        return new MainFragment(Color.GREEN);
    }
    public static MainFragment Frag3() {
        return new MainFragment(Color.BLUE);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        View view = inflater.inflate(mResourceId, container, false);
        view.setBackgroundColor(mColour);
        return view;
    }
}

frag.xml

<?xml version="1.0" encoding="utf-8"?>
<com.example.slidingpanels.SlidingImageView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/SlidingImageView1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:src="@drawable/ic_launcher" >

</com.example.slidingpanels.SlidingImageView>

SlidingImageView.java

public class SlidingImageView extends ImageView {

    public SlidingImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

    public float getXFraction() {

        int width = this.getWidth();
        return (width == 0) ? 0 : getX() / (float) width;
    }

    public void setXFraction(float xFraction) {

        int width = this.getWidth();
        setX((width > 0) ? (xFraction * width) : 0);
    }
}

最后,我会包含我slide_in_left.xml

<?xml version="1.0" encoding="utf-8"?>
<set>
    <objectAnimator 
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:propertyName="xFraction" 
        android:valueType="floatType"
        android:valueFrom="-1"
        android:valueTo="0" 
        android:duration="500" />
</set>

Answer 1:

我有完全一样的问题...

闪烁/毛刺,因为当setXFraction首次调用引起其前onMeasure发生等getWidth()返回0的含义为第一引出框的片段是在未卷动位置,下一个呼叫的onMeasure及其拉伸后会发生在正确的地方作为的getWidth现在返回有效的数据。

我发现该溶液是保存X分数在视图对象作为浮子,然后覆盖onMeasure()和重新做setTranslationX,使用mXfract * measureSpec。

作品对我来说,代码片段如下:

public class SlidingFrameLayout extends FrameLayout {

  private static final String TAG = SlidingFrameLayout.class.getSimpleName();

  private float mXfract=0f;
  private float mYfract=0f;

  public SlidingFrameLayout(Context context) {
      super(context);
  }

  public SlidingFrameLayout(Context context, AttributeSet attrs) {
      super(context, attrs);
  }

  public SlidingFrameLayout(Context context, AttributeSet attrs, int defStyle) {
      super(context, attrs, defStyle);
  }

  public void setYFraction(final float fraction) {
      mYfract=fraction;
      float translationY = getHeight() * fraction;
      setTranslationY(translationY);
  }

  public float getYFraction() {
      return mYfract;
  }

  public void setXFraction(final float fraction) {
      mXfract=fraction;
      float translationX = getWidth() * fraction;
      setTranslationX(translationX);
  }

  public float getXFraction() {
      return mXfract;
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      super.onMeasure(widthMeasureSpec, heightMeasureSpec);
      int width = MeasureSpec.getSize(widthMeasureSpec);
      int height = MeasureSpec.getSize(heightMeasureSpec);
      // Correct any translations set before the measure was set
      setTranslationX(mXfract*width);
      setTranslationY(mYfract*height);
  }
}

编辑:要为宽度/高度,而不是调用中使用measurespec。



文章来源: FragmentTransaction animation is working but appears glitchy