根据新的Bottom Bar解决方案,我找不到实现这样的东西的想法:
Gif与新的活动
我知道点击图片后会打开新的"活动",但如何在不消失底部栏的情况下打开它?
编辑
我说的是一个例子,在"音乐"选项卡中,用户点击Kodaline专辑,然后它会显示一些新的活动。
没有启动新活动,否则底部导航栏会在一瞬间消失。基本思想是有一个活动,根据选择的项目将视图或片段膨胀到容器中。我建议使用视图而不是片段,因为某些FragmentTransaction错误特别难以追踪,而且在定义自定义视图时,您可以完全控制FragmentManager。示例gif将底部导航的可见性设置为View。在滚动过程中移动并设置底部导航的动画。
MainActivity.java
public class MainActivity extends Activity implements
YourBottomNavView.OnItemClickListener {
ViewGroup viewContainer;
YourBottomNavView bottomNav;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewContainer = findViewById(R.id.view_container);
bottomNav = findViewById(R.id.bottom_nav);
bottomNav.setItemClickListener(this);
}
@Override
public void onItemClicked(int item) {
viewContainer.removeAllViews();
View nextView = getView(item);
viewContainer.addView(nextView);
}
private View getView(int item) {
//Insert logic
}
}
R.layout.activity_main
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/view_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/header"/>
<YourBottomNavView
android:id="@+id/bottom_nav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
或者,您可以使用碎片注入到您的viewContainer中,但我发现使用普通的旧视图比碎片可能向您抛出的随机错误要可靠得多。
下面是一个自定义视图的例子
public class YourAwesomeView extends LinearLayout {
public YourAwesomeView(Context context) {
super(context);
init();
}
public YourAwesomeView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
inflate(getContext(), R.layout.YOUR_AWESOME_VIEW, this);
}
}
YourBottomNavView.java
public class YourBottomNavView extends LinearLayout {
View button1, button2, button3;
View root;
OnItemClickListener onItemClickListener;
public YourBottomNavView(Context context) {
super(context);
init();
}
public YourBottomNavView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
inflate(getContext(), R.layout.view_bottom_nav, this);
root = findViewById(R.id.root);
button1 = findViewById(R.id.button1_container);
button2 = findViewById(R.id.button2_container);
button3 = findViewById(R.id.button3_container);
//The button clicks need to communicate to something like the
//activity to inflate your new view / fragment. I personally
//define an OnItemClickedListener interface in the
//YourBottomNavView class that the MainActivity implements
//and I have the activity decide which view to inflate into
//its frame layout. This is also where you can do cool
//animations like we saw from the GIFs.
//This is also where you can swap out drawables to color the
//ImageViews differently.
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onItemClickListener.onItemClicked(0);
root.setBackgroundColor(0xFF0000);
}
});
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onItemClickListener.onItemClicked(1);
root.setBackgroundColor(0x00FF00);
}
});
button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onItemClickListener.onItemClicked(2);
root.setBackgroundColor(0x0000FF);
}
});
}
public void setItemClickListener(OnItemClickListener listener) {
onItemClickListener = listener;
}
public interface OnItemClickListener {
void onItemClicked(int item);
}
}
R.layout.view_bottom.nav
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="@color/default_color"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/button1_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:orientation="vertical"
android:weight="1">
<ImageView android:id="@+id/image1"
android:layout_width="24dp"
android:layout_height="24dp"
src="@drawable/icon1"/>
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout
android:id="@+id/button2_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:orientation="vertical"
android:weight="1">
<ImageView android:id="@+id/image2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
src="@drawable/icon1"/>
<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout
android:id="@+id/button3_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:orientation="vertical"
android:weight="1">
<ImageView android:id="@+id/button3"
android:layout_width="24dp"
android:layout_height="24dp"
src="@drawable/icon3"/>
<TextView
android:id="@+id/text3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
经过几个月的思考,我的应用程序出现了这个问题。我发现,只使用Android应用程序中使用的MVC模式很难实现所需的行为,因为沿着应用程序流将Main Activity保持在屏幕上会使此类过载。
尽管谷歌安卓教程传播了这种MVC思想,但真正的谷歌应用程序和设计示例(比如你说的这个漂亮的音乐播放器)在架构和代码组织方面遥遥领先。
这个问题的真正解决方案是使用MVC之外的另一种模式来解耦逻辑和视图。您可能想了解Clean Architecture中使用的模式,以便在几个类中解耦繁重的代码,并在屏幕上保持相同的"活动"(带底部条的那个)。