android - 带有支持库 (14+) 的片段转换 API 不执行任何转换
问题描述
我有一个更大的项目,当用户在应用程序中导航时,我需要在片段之间转换时应用一些动画。
到目前为止,我已经在setCustomAnimation
上使用了方法FragmentTransaction
,它的效果和预期的一样好,但是在需要动画视图时它非常有限。
所以我决定继续使用 Transition API。好消息,它是支持库的一部分(通过 AndroidX),并且sharedElement
withtransitionName
也被向后移植。因此只需编写一组代码,无需进行 SDK INT 检查!
但是我失败了,完全失败了,因为我的项目很大,所以我决定创建一个新的,非常简单,直截了当,看看我是否做对了。
但我没有做对!所以,在这一点上,我想分享我这个非常简单的项目的代码。如果有人能理解我为什么没有过渡,我将非常感激。
无论如何,代码:
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
public final static String TRANSITION_NAME = "test_transition_name";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_holder, new FragmentOne(), "FragmentOne")
.commit();
}
}
如您所见,没什么,我立即触发该过程以显示我的第一个片段(FragmentOne
)。
无论如何,它的布局:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/fragment_holder"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
</androidx.constraintlayout.widget.ConstraintLayout>
说到片段,就像我说的,我说的很严格,所以我有两个片段,即FragmentOne
和FragmentTwo
。
两个片段都具有相似的布局:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FragmentOne">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="@+id/text_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="40sp"
android:textStyle="bold"
android:gravity="top|center_horizontal"
android:textColor="@android:color/white"
android:background="@android:color/black"
android:transitionName="test_transition_name"
android:text="Hello From Fragment ONE" />
</FrameLayout>
和
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FragmentTwo">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="@+id/text_two"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="40sp"
android:textStyle="bold"
android:gravity="bottom|center_horizontal"
android:layout_gravity="bottom"
android:textColor="@android:color/white"
android:background="@android:color/black"
android:transitionName="test_transition_name"
android:text="Hello from fragment TWO" />
</FrameLayout>
如您所见,这两个片段布局之间的唯一区别是文本内容(我将其放大)和重力。在FragmentOne
中,文本位于布局的顶部,而在FragmentTwo
. 没有什么特别简单的。
在这一点上,我的目标是使用 Transition API(Android X 版本)在这两个文本之间进行动画转换。
- 从
FragmentOne
到FragmentTwo
时,文本向底部滑动/移动 - 返回时,文本滑动/向上移动(反向)。
下面是这两个片段的代码:
片段一
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
/**
* A simple {@link Fragment} subclass.
*/
public class FragmentOne extends Fragment {
public FragmentOne() {
// Required empty public constructor
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setSharedElementReturnTransition(new AutoTransition());
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_one, container, false);
}
@Override
public void onViewCreated(@NonNull final View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ViewCompat.setTransitionName(view.findViewById(R.id.text_one), MainActivity.TRANSITION_NAME);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getFragmentManager()
.beginTransaction()
.addSharedElement(view.findViewById(R.id.text_one), MainActivity.TRANSITION_NAME)
.replace(R.id.fragment_holder, new FragmentTwo(), "FragmentTwo")
.addToBackStack("FragmentTwo")
.commit();
}
});
}
}
片段二
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
import androidx.transition.AutoTransition;
import androidx.transition.Transition;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {@link Fragment} subclass.
*/
public class FragmentTwo extends Fragment {
public FragmentTwo() {
// Required empty public constructor
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setSharedElementEnterTransition(new AutoTransition());
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment__two, container, false);
}
@Override
public void onViewCreated(@NonNull final View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ViewCompat.setTransitionName(view.findViewById(R.id.text_two), MainActivity.TRANSITION_NAME);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getFragmentManager().popBackStack();
}
});
}
}
你去吧。这里没有额外/花哨的代码。
简而言之:
- 我
addSharedElement
在我的FragmentTransaction
. 名称与在文件中声明的静态变量相同MainActivity
- 正如我所说,我想一直使用 Android X 库,所以所有类都来自 Android X 包,我什
ViewCompat#setTransitionName
至在我的模拟器运行 Android 9 Pie 时将转换名称设置为我的共享视图。
我在哪里弄错了?为什么根本没有过渡?
[更新 1]
我注意到我的片段布局(由 Android Studio 在创建片段时生成)同时TextViews
用于match_parent
宽度和高度。所以,我想没有太多的滑动/移动可以做,因为两个视图具有相同的边界(匹配相同大小的父级)。
我用更好的布局更新了上面的帖子,但结果完全相同。我什至添加了一些背景以正确查看视图边界,并直接在 XML 中设置转换名称,虽然这样做不向后兼容,但我这样做是为了测试。
解决方案
推荐阅读
- laravel-5 - 突然主页重定向到设置#/订阅
- css - CSS 转换在 IE 11 中不起作用
- javascript - 从动态文本区域获取价值
- linux - rm -rf 和 rm -r 有什么区别?
- angular - *ngFor="let.." 中的 Angular 2“资源 URL 上下文中使用的不安全值”
- c# - CS1503 C# 参数 1:无法从“Project.Vector2”转换为“System.Predicate”
" - javascript - 是否可以更改本地 URL
- laravel - 状态:405,状态文本:“方法不允许”,在 axios .post laravel
- spring-boot - 在 docker 容器上运行 ConfigServer 和 EurekaServer 时无法获取配置文件
- javascript - 如何让 P5JS 线在函数 mousePressed() 上滑动到新位置