我正在尝试在单个片段中创建Master / Detail事务。我想过使用LinearLayout作为我的头文件编辑文本的容器。然后是RecyclerView以获取详细信息。
如何实现LinearLayout的折叠/扩展,类似于CollapsingToolbar效果?
这是我正在尝试做的截图。
到目前为止我的xml代码。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@color/colorAccent"
android:padding="@dimen/activity_horizontal_margin">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_date_range_black_24dp"
android:tint="@android:color/darker_gray" />
<android.support.v4.widget.Space
android:layout_width="@dimen/activity_horizontal_margin"
android:layout_height="wrap_content" />
<android.support.design.widget.TextInputLayout
android:id="@+id/date_til"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Date">
<android.support.design.widget.TextInputEditText
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cursorVisible="false"
android:focusable="false"
android:longClickable="false" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_store_black_24dp"
android:tint="@android:color/darker_gray" />
<android.support.v4.widget.Space
android:layout_width="@dimen/activity_horizontal_margin"
android:layout_height="wrap_content" />
<android.support.design.widget.TextInputLayout
android:id="@+id/store_til"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Store">
<android.support.design.widget.TextInputEditText
android:id="@+id/store"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_place_black_24dp"
android:tint="@android:color/darker_gray" />
<android.support.v4.widget.Space
android:layout_width="@dimen/activity_horizontal_margin"
android:layout_height="wrap_content" />
<android.support.design.widget.TextInputLayout
android:id="@+id/location_til"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputEditText
android:id="@+id/location"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Location" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
app:layoutManager="LinearLayoutManager"
tools:listitem="@layout/list_car" />
</LinearLayout>
另外,不确定是否可以使用CollapsingToolbar完成此操作,因为我大多只看到ImageView在工具栏中折叠。
提供任何帮助。
更新:基本上我想在这里做的是能够在向上滚动时折叠标题视图。然后在向下滚动时展开。
答案 0 :(得分:4)
您可以使用计时器并逐渐缩小顶部栏的LinearLayout的高度/边距(编辑: Anton Maiorov的答案中的缺陷在此处修复)
请参阅下面的代码段(在设备上测试)
方法I: Anton Maiorov的答案,修复了缺陷,这比下面的第二个实现简单得多
public class MainActivity extends AppCompatActivity {
LinearLayout toolbar;
int mOriginalHeight;
boolean initialSizeObtained = false;
boolean isShrink = false;
Animation _hideAnimation = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) toolbar.getLayoutParams();
params.topMargin = -(int) (mOriginalHeight * interpolatedTime);
toolbar.setLayoutParams(params);
}
};
Animation _showAnimation = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) toolbar.getLayoutParams();
params.topMargin = (int) (mOriginalHeight * (interpolatedTime - 1));
toolbar.setLayoutParams(params);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (LinearLayout) findViewById(R.id.toolbar);
//Get the original height, which is measured according to WRAP_CONTENT
toolbar.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (initialSizeObtained)
return;
initialSizeObtained = true;
mOriginalHeight = toolbar.getMeasuredHeight();
}
});
_hideAnimation.setDuration(2000);
_showAnimation.setDuration(2000);
}
//Click on the Olimpic image --> Toggles the top toolbar
public void ToggleTopBar(View view) {
isShrink = !isShrink;
toolbar.clearAnimation(); //Important
toolbar.startAnimation(isShrink? _hideAnimation : _showAnimation);
}
}
方法II:我的原始答案是通过更改工具栏的高度,还可以手动使用计时器,这更为复杂:
public class MainActivity extends AppCompatActivity {
LinearLayout toolbar;
int mOriginalHeight;
boolean initialSizeObtained = false;
int currentHeight;
boolean isShrink = false;
Timer timer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (LinearLayout) findViewById(R.id.toolbar);
toolbar.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (initialSizeObtained)
return;
initialSizeObtained = true;
mOriginalHeight = toolbar.getMeasuredHeight();
currentHeight = mOriginalHeight;
Log.d("Demo", "Original height is " + mOriginalHeight);
}
});
}
//Click on the Olimpic image --> Toggles the top toolbar
public void ToggleTopBar(View view) {
isShrink = !isShrink;
Resize(isShrink, toolbar, 250);
}
void Resize(final boolean isShrink, final LinearLayout layout, final int minHeight) {
final int H0 = mOriginalHeight;
timer = runTimerAction(10, new Runnable() {
public void run() {
Log.d("demo", "Current Height= " + currentHeight);
if (isShrink && currentHeight > minHeight) {
currentHeight -= 10;
layout.getLayoutParams().height = currentHeight;
refreshToolbar();
} else if (!isShrink && currentHeight < H0) {
currentHeight += 10;
layout.getLayoutParams().height = currentHeight;
refreshToolbar();
} else {
layout.getLayoutParams().height = isShrink ? minHeight : H0;
refreshToolbar();
if (timer != null)
timer.cancel();
}
}
}
);
}
public void refreshToolbar() {
runOnUiThread(new Runnable() {
@Override
public void run() {
toolbar.requestLayout();
}
});
}
答案 1 :(得分:2)
使用David的评论改进了我的回答。
我会动画&#34; topMargin&#34;你的标题:
LinearLayout _headerLayout; // expected to be set in "onCreateView"
int _headerHeight; // expected to be set in "onCreateView" as _headerHeight = getHeaderHeight();
Animation _hideAnimation = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) _headerLayout.getLayoutParams();
params.topMargin = -(int) (_headerHeight * interpolatedTime);
_headerLayout.setLayoutParams(params);
}
};
Animation _showAnimation = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) _headerLayout.getLayoutParams();
params.topMargin = (int) (_headerHeight * (interpolatedTime - 1));
_headerLayout.setLayoutParams(params);
}
};
private int getHeaderHeight()
{
_headerLayout.measure(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
return _headerLayout.getMeasuredHeight();
}
隐藏标题:
_headerLayout.clearAnimation();
_headerLayout.startAnimation(_hideAnimation);
显示标题:
_headerLayout.clearAnimation();
_headerLayout.startAnimation(_showAnimation);
您还可以轻松设置动画的持续时间:
_hideAnimation.setDuration(2000) // will hide in 2 seconds
_showAnimation.setDuration(2000) // will show in 2 seconds
答案 2 :(得分:1)
试试这个我添加了Coordinator和CollapsingToolbarLayput
<?xml version="1.0" encoding="utf-8"?>
<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:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="15dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorAccent"
android:orientation="vertical"
android:padding="@dimen/activity_horizontal_margin">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_date_range_black_24dp"
android:tint="@android:color/darker_gray" />
<android.support.v4.widget.Space
android:layout_width="@dimen/activity_horizontal_margin"
android:layout_height="wrap_content" />
<android.support.design.widget.TextInputLayout
android:id="@+id/date_til"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Date">
<android.support.design.widget.TextInputEditText
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cursorVisible="false"
android:focusable="false"
android:longClickable="false" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_store_black_24dp"
android:layout_gravity="center"
android:tint="@android:color/darker_gray" />
<android.support.v4.widget.Space
android:layout_width="@dimen/activity_horizontal_margin"
android:layout_height="wrap_content" />
<android.support.design.widget.TextInputLayout
android:id="@+id/store_til"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Store">
<android.support.design.widget.TextInputEditText
android:id="@+id/store"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_place_black_24dp"
android:tint="@android:color/darker_gray" />
<android.support.v4.widget.Space
android:layout_width="@dimen/activity_horizontal_margin"
android:layout_height="wrap_content" />
<android.support.design.widget.TextInputLayout
android:id="@+id/location_til"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputEditText
android:id="@+id/location"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Location" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
</LinearLayout>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:listitem="@layout/list_car"
app:layoutManager="LinearLayoutManager" />
我希望这可以帮到你。
答案 3 :(得分:0)
基于 RIP's tutorial,您可以使用以下代码段折叠或展开视图。
public class ViewAnimationUtils {
public static void expand(final View v) {
v.measure(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
final int targtetHeight = v.getMeasuredHeight();
v.getLayoutParams().height = 0;
v.setVisibility(View.VISIBLE);
Animation a = new Animation()
{
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
v.getLayoutParams().height = interpolatedTime == 1
? LayoutParams.WRAP_CONTENT
: (int)(targtetHeight * interpolatedTime);
v.requestLayout();
}
@Override
public boolean willChangeBounds() {
return true;
}
};
a.setDuration((int)(targtetHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
public static void collapse(final View v) {
final int initialHeight = v.getMeasuredHeight();
Animation a = new Animation()
{
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if(interpolatedTime == 1){
v.setVisibility(View.GONE);
}else{
v.getLayoutParams().height = initialHeight - (int)(initialHeight * interpolatedTime);
v.requestLayout();
}
}
@Override
public boolean willChangeBounds() {
return true;
}
};
a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
}
此外,要指定应用于动画视图的逻辑,在您的情况下,可以使用 ScrollListener
之类的
private fun RecyclerView.onViewScroll(title: String): OnScrollListener {
return object : OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, state: Int) {
super.onScrollStateChanged(recyclerView, state)
rootView.findViewById<ConstraintLayout>(R.id.views_menu_header).let { layout ->
if(state == SCROLL_STATE_DRAGGING) {
collapse(layout)
}
}
}
}
}
然后,将侦听器附加到您的回收器
findViewById<RecyclerView>(R.id.views_menu_items).apply { addOnScrollListener(onViewScroll(title)) }
每当 R.id.views_menu_header
开始被拖动时都会折叠 R.id.views_menu_items
。