我正在做一个项目,我想按照材料设计使用圆形显示效果。项目有minSDK = 11,所以为了与pre-Lollipop设备兼容,我使用这个库https://github.com/ozodrukh/CircularReveal
我有一个带有FloatingActionButton的片段,当点击时,它会在CardView中转换自己,就像这里描述的FAB转换。
一旦卡片显示,它有一个按钮来恢复动画,将卡片重新转换为FAB。现在我的问题是这样的:假设一个用户点击FAB, CardView显示出来。现在用户旋转他的设备,所以活动重置片段。我想要实现的是卡片保持可见和显示,而FAB应该是禁用和不可见的。问题是,如果我只是在我的FAB上使用setVisibility(View.INVISIBLE)
,它不起作用(请注意,如果我在设置它不可见后使用getVisibility()
,它正确地返回我值4 ==视图。看不见,但工厂仍然可见)。我必须将setVisibility(...)
调用包装在postDelayed()
中,至少有50-100毫秒的延迟,以使晶圆厂不可见。
所以我的问题是:我做的事情是正确的还是有更好的方法来完成我想要的(因为它对我来说似乎很丑陋)?
下面是一些代码。这是片段的XML布局:
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/my_appbar"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_expanded_height"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="70dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/ToolbarPopupTheme"
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
...
<io.codetail.widget.RevealFrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/my_fragment" />
</io.codetail.widget.RevealFrameLayout>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
app:fabSize="mini"
app:layout_anchor="@+id/my_appbar"
app:layout_anchorGravity="bottom|left|start" />
</android.support.design.widget.CoordinatorLayout>
这是包含CardView的XML布局:
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:layout_gravity="center"
card_view:cardCornerRadius="2dp"
android:visibility="invisible"
android:focusableInTouchMode="true">
<RelativeLayout android:layout_width="match_parent"
android:layout_height="match_parent">
...
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="end">
<Button android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Ok" />
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cancel" />
</LinearLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
这是我的片段的代码:
public class MyFragment extends Fragment {
private static final String CARD_OPEN_TAG = "CARD_OPEN_TAG";
public static MyFragment newInstance(){
return new MyFragment();
}
private int cardOpen;
private FloatingActionButton fabAddPublication;
private CardView card;
private Button cardCancel;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_magazines, container, false);
toolbar = (Toolbar) rootView.findViewById(R.id.layout);
...
// Initialize view status
if (savedInstanceState != null){
cardOpen = savedInstanceState.getInt(CARD_OPEN_TAG);
} else {
cardOpen = -1;
}
...
// Get FAB reference
fab = (FloatingActionButton) rootView.findViewById(R.id.fab_id);
// Get card reference
card = (CardView) rootView.findViewById(R.id.card_id);
editorPublication.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// Using this event because I need my card to be measured to move correctly fab at his center
if (cardOpen != -1){
// Move FAB to center of card
fab.setTranslationX(coordX); // WORKS
fab.setTranslationY(coordY); // WORKS
// fab.setVisibility(View.INVISIBLE) -> DOESN'T WORK, fab remain visible on top and at center of my card
// Ugly workaround
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// Hide FAB
fab.setVisibility(View.INVISIBLE);
}
}, 50); // Sometimes fails: if device/emulator use too much time to "rotate" screen, fab stay visible
// Remove listener
ViewTreeObserver obs = card.getViewTreeObserver();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
obs.removeOnGlobalLayoutListener(this);
else obs.removeGlobalOnLayoutListener(this);
}
}
});
if (editorOpen != -1){
fab.setEnabled(false); // WORKS
card.setVisibility(View.VISIBLE); // WORKS
}
// Get editors buttons reference
cardCancel = (Button) card.findViewById(R.id.card_cancel_id);
// Set FAB listener
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Explode FAB
explodeFab(fab, card); // This method trigger the reveal animation
cardOpen = card.getId();
}
});
// Set editors button listeners
cardCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Implode FAB
implodeFAB(fab, card); // This card reverts the reveal animation
cardOpen = -1;
}
});
...
return rootView;
}
@Override
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
...
outState.putInt(CARD_OPEN_TAG, cardOpen);
}
}
我不认为你这样做是正确的,原因如下:
1。
你正在使用的圆形显示库与Android 11到17(3.0到4.2)的硬件加速不兼容。它使用了Canvas.clipPath()——这个方法只在Android 4.3之前的软件中实现。这意味着你必须关闭硬件加速,否则你的应用程序会在不支持的OpenGL调用时崩溃。
剪辑布局的最佳方法是使用Canvas.saveLayer()/restorerelayer()。这是支持所有设备,获得抗锯齿图像和正确支持invalidate/layout/draw流程的唯一方法。2。
依靠计时器和布局监听器来改变布局意味着有些东西不适合你。每个更改都可以直接执行,而无需等待。你只需要为这段代码找到合适的位置。
计时器也可以在应用程序处于后台时触发。这意味着当试图从Timer线程访问UI时,它会崩溃。
也许你在代码的某个地方调用setVisibility(true),这就是为什么你的FAB是可见的?设置可见性是可以的,应该没有任何延迟呼叫。只需将可视性保存为FAB的状态,并在方向更改后恢复即可。
如果你希望将FAB放置在工具栏的中心,将它们都包裹在一个框架布局(wrap_content)中,并将FAB放置在layout_gravity="center"的位置。这应该允许您删除布局侦听器。
3。
的支持。CardView是坏的,根本不应该使用。它在Lollipop和旧系统上的外观和工作方式略有不同。阴影是不同的,填充是不同的,内容剪辑不能在pre-Lollipop设备上工作,等等。这就是为什么很难在所有平台上获得一致的好结果。
你应该考虑使用普通的布局。
4。
有些动画看起来很酷,但很难实现,没有任何价值,很快就会变得令人恼火,因为用户每次点击按钮都必须等待动画完成。
我不是说不适合您的情况,但您可以考虑删除转换并使用下拉菜单,底部工作表,静态工具栏或对话框来实现此目的。