Asa*_*saf 30 android android-fragments material-design
在android材料设计原则页面上,其中一个示例显示了FAB扩展到新的全屏.(在"全屏"下)
我试图在我的应用程序中实现相同的效果,但收效甚微.
我设法使用此代码作为参考创建了一个扩展为视图的FAB:https://gist.github.com/chris95x8/882b5c5d0aa2096236ba.
它有效,但我想知道我是否可以对活动过渡应用相同的效果.我已经尝试过查找并自己玩它但找不到任何可行的东西.
我知道我可以让FAB扩展成片段而不是一个全新的活动,但我不确定这是做什么的,以及这是否是最佳的.
所以我的问题是,有没有办法将fab扩展显示效果实现为活动转换,还是应该只显示一个新片段?
yww*_*ynm 29
我正在开发一个应用程序,将一个扩展FloatingActionButton
为一个新的Activity
.我不确定如果你喜欢我的实现,但请先看图片:
所以第一张图片显示MainActivity
,最后一张图片显示,SecondActivity
从FAB"扩展".
现在,我想提一下,我实际上并没有将 FAB 扩展为新的,Activity
但我可以让用户感觉新页面是从FAB扩展的,我认为这对开发人员和用户来说都足够了.
这是实施:
制备:
FloatingActionButton
当然,ABakedBezierInterpolator
控制揭示动画,并使其材质风格.脚步:
像这样创建activity_main.xml:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--Your main content here-->
<RevealLayout
android:id="@+id/reveal_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible">
<View
android:id="@+id/reveal_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"/>
</RevealLayout>
</FrameLayout>
Run Code Online (Sandbox Code Playgroud)查看视图:
mRevealLayout = (RevealLayout) findViewById(R.id.reveal_layout);
mRevealView = findViewById(R.id.reveal_view);
Run Code Online (Sandbox Code Playgroud)用户单击FAB时展开:
mFab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mFab.setClickable(false); // Avoid naughty guys clicking FAB again and again...
int[] location = new int[2];
mFab.getLocationOnScreen(location);
location[0] += mFab.getWidth() / 2;
location[1] += mFab.getHeight() / 2;
final Intent intent = new Intent(MainActivity.this, SecondActivity.class);
mRevealView.setVisibility(View.VISIBLE);
mRevealLayout.setVisibility(View.VISIBLE);
mRevealLayout.show(location[0], location[1]); // Expand from center of FAB. Actually, it just plays reveal animation.
mFab.postDelayed(new Runnable() {
@Override
public void run() {
startActivity(intent);
/**
* Without using R.anim.hold, the screen will flash because of transition
* of Activities.
*/
overridePendingTransition(0, R.anim.hold);
}
}, 600); // 600 is default duration of reveal animation in RevealLayout
mFab.postDelayed(new Runnable() {
@Override
public void run() {
mFab.setClickable(true);
mRevealLayout.setVisibility(View.INVISIBLE);
mViewToReveal.setVisibility(View.INVISIBLE);
}
}, 960); // Or some numbers larger than 600.
}
});
Run Code Online (Sandbox Code Playgroud)
这里是res/anim中的hold.xml:
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<translate
android:duration="960" <!-- Enough-large time is OK -->
android:fromXDelta="0%"
android:fromYDelta="0%"
android:toXDelta="0%"
android:toYDelta="0%"/>
</set>
Run Code Online (Sandbox Code Playgroud)就这样.
改进:
RevealLayout
对于API 17(Android 4.2)下的设备有一个错误(播放矩形而不是圆形显示动画),你可以在它的构造函数中添加这些行:
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
Run Code Online (Sandbox Code Playgroud)如果你SecondActivity
包含复杂的内容,在View
layout.xml中用作reveal_view 的简单是不够/完美的.您可以在RevealLayout
reveal_layout中包含第二个布局.如果第二个布局在每次都不会出现相同的情况,那么看起来很浪费并且难以控制.但对我来说,它会.如果你愿意,你可以做其他改进.
如果要实现"材质设计指南"中显示的完全相同的动画,可以将layout_height设置RevealLayout
为特定数字而不是match_parent.扩展动画结束后(或动画播放后的某个时间,这应该使动画的整个过程流畅),然后您可以为translateY设置动画.重要的是,通过控制动画持续时间来视觉欺骗用户.
最后,这是我自己的经验/尝试,我是开发Android应用程序的初学者.如果有任何错误/进一步改进,请留下评论/编辑我的答案.谢谢.
我做了一个自定义活动,根据这个问题循环显示新活动的转换,处理CircularRevealAnimation以及活动结束时的反向效果:
public class RevealActivity extends AppCompatActivity {
private View revealView;
public static final String REVEAL_X="REVEAL_X";
public static final String REVEAL_Y="REVEAL_Y";
public void showRevealEffect(Bundle savedInstanceState, final View rootView) {
revealView=rootView;
if (savedInstanceState == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
rootView.setVisibility(View.INVISIBLE);
ViewTreeObserver viewTreeObserver = rootView.getViewTreeObserver();
if(viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
circularRevealActivity(rootView);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
rootView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
rootView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
});
}
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void circularRevealActivity(View rootView) {
int cx = getIntent().getIntExtra(REVEAL_X, 0);
int cy = getIntent().getIntExtra(REVEAL_Y, 0);
float finalRadius = Math.max(rootView.getWidth(), rootView.getHeight());
// create the animator for this view (the start radius is zero)
Animator circularReveal = ViewAnimationUtils.createCircularReveal(rootView, cx, cy, 0, finalRadius);
circularReveal.setDuration(400);
// make the view visible and start the animation
rootView.setVisibility(View.VISIBLE);
circularReveal.start();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home: onBackPressed();break;
return super.onOptionsItemSelected(item);
}
}
@Override
public void onBackPressed() {
destroyActivity(revealView);
}
private void destroyActivity(View rootView) {
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP)
destroyCircularRevealActivity(rootView);
else
finish();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void destroyCircularRevealActivity(final View rootView) {
int cx = getIntent().getIntExtra(REVEAL_X, 0);
int cy = getIntent().getIntExtra(REVEAL_Y, 0);
float finalRadius = Math.max(rootView.getWidth(), rootView.getHeight());
// create the animator for this view (the start radius is zero)
Animator circularReveal = ViewAnimationUtils.createCircularReveal(rootView, cx, cy, finalRadius, 0);
circularReveal.setDuration(400);
circularReveal.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
rootView.setVisibility(View.INVISIBLE);
finishAfterTransition();
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
// make the view visible and start the animation
rootView.setVisibility(View.VISIBLE);
circularReveal.start();
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用自己的活动扩展它,并在onCreate中调用方法'showRevealEffect',如下所示:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_activity_layout);
//your code
View root= findViewById(R.id.your_root_id);
showRevealEffect(savedInstanceState, root);
}
Run Code Online (Sandbox Code Playgroud)
你还必须使用像这样的透明主题:
<style name="Theme.Transparent" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="colorControlNormal">@android:color/white</item>
</style>
Run Code Online (Sandbox Code Playgroud)
最后,要启动此活动,您应该通过额外的动画应该开始的坐标传递:
int[] location = new int[2];
fab.getLocationOnScreen(location);
Intent intent = new Intent(this, YourRevealActivity.class);
intent.putExtra(SearchActivity.REVEAL_X, location[0]);
intent.putExtra(SearchActivity.REVEAL_Y, location[1]);
startActivity(intent);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
21659 次 |
最近记录: |