我不知道这是否是重复的问题,但我没有找到任何解决方案。
问题是,有一个屏幕在所有屏幕上都有类似的视图,屏幕是碎片。
所以,我想创建一个基本片段,并希望在所有子片段中扩展这个基本片段。
我在Google上找到了演示示例,但我没有找到任何解决方案。
我不知道从哪里开始。
请帮帮我。
我找到了这个链接,但不太清楚:
BaseFragment.java
public class BaseFragment extends Fragment {
public BaseFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_base, container, false);
}
}
ChildFragment.Java
public class ChildFragment extends BaseFragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_child, container, false);
}
}
现在,fragment_child布局中有一个TextView。当我运行应用程序时显示 但是fragment_base中还有另外两个视图,它们没有显示......
答案 0 :(得分:7)
抽象类方法?
我理解你在这里做什么(继承)。但正如@hobokent指出的那样,仅通过继承BaseClass将不会在BaseClass Layout之上包含您的childView布局。 有很多方法可以解决这个问题
让我们来看看这个解决方案。
创建一个扩展Fragment类的抽象类(This 将是BaseClass)。
制作一个将返回布局的抽象方法。
在ChildClass中为您的抽象方法提供实现。
以下是代码段。
BaseClass的
public abstract class BasicFragment extends Fragment {
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
public View onCreateView(LayoutInflater inflater,ViewGroup parent, Bundle savedInstanseState)
{
View view = provideYourFragmentView(inflater,parent,savedInstanseState);
return view;
}
public abstract View provideYourFragmentView(LayoutInflater inflater,ViewGroup parent, Bundle savedInstanceState);
}
ChildClass
public class ImageFragment extends BasicFragment{
@Override
public View provideYourFragmentView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.image_fragment,parent,false);
//Now specific components here (you can initialize Buttons etc)
return view;
}
}
对于您的特定要求,如果您希望在子类布局中显示相同的布局。您可以创建一个返回布局的方法,也可以在子布局中为BaseClass Layout创建占位符,并使用child.add(base_layout)在childLayout中添加BaseClass布局。 这又是另一种设计方案 您还可以在Activity布局中放置一个公共布局,并在片段的Activity占位符中添加片段。 有很多可能的解决方案。
我没有任何特定于您的要求的代码,但这里是我为TabLayout实现此方法的示例,其中每个标签是不同的片段,具有不同的布局。
Github full code sample
答案 1 :(得分:1)
扩展片段不会包含视图,这些视图来自您扩展的布局,因此您无法在子片段中看到fragment_base中的文本视图。
相反,创建和使用自定义视图/复合视图可以让您受益,然后可以在其他片段中重复使用。
您可以在此处阅读化合物视图:
https://medium.com/@Sserra90/android-writing-a-compound-view-1eacbf1957fc
答案 2 :(得分:0)
BaseFragment扩展了Fragment类,然后你的其他Fragments扩展了BaseFragment
public class BaseFragment extends Fragment
public class AboutFragment extends BaseFragment
如果你想要其他布局:
View headView = LayoutInflater.from(getContext()).inflate(R.layout. - your Fragment layout - , null, false);
这对我有用。
希望它有所帮助。
答案 3 :(得分:0)
您可以通过为每个子片段包含基本布局来实现此目的。然后,您需要将基本片段中的视图绑定到基本布局中的所有基本视图。对于子视图布局,您需要将其绑定在子片段中。
这里的步骤:
创建基本片段布局(fragment_base.xml):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout>
<!-- Declare your view here -->
<android.support.v7.widget.AppCompatTextView
android:id="@+id/sample_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sample"/>
</RelativeLayout>
创建基本片段
public class BaseFragment extends Fragment {
public BaseFragment() {
// Required empty public constructor
}
...
}
在基本片段中创建一个基本方法来绑定视图。这将被重写并在您的子片段中重用。在这里,我们使用bindView()
名称:
public class BaseFragment extends Fragment {
protected AppCompatTextView mTvSample;
...
protected void bindView(View view) {
mTvSample = view.findViewById(R.id.sample_tv);
}
...
}
通过重用基本布局来创建子布局。您可以使用包含。它应该是这样的(fragment_child.xml):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout>
<include
layout="@layout/fragment_base"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<!-- Child view -->
<android.support.v7.widget.AppCompatTextView
android:id="@+id/child_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Child Sample"/>
</RelativeLayout>
现在,您可以通过扩展基本片段来创建子片段。您需要记住使用并覆盖bindView()
。所以,你需要做这样的事情:
public class ChildFragment extends BaseFragment {
private AppCompatTextView mTvChild;
public ChildFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_child, container, false);
bindView(view);
return view;
}
@Ovverride
protected void bindView(View view) {
super.bindView(view); //call base method to bind the base view
mTvChild = view.findViewById(R.id.child_tv);
}
}
答案 4 :(得分:0)
我已经实现了此结构,您可以在其中将BaseFragment布局显示在ChildFragment布局中。基本上,我使用ViewStub来实现该解决方案。 VewStub是一种占位符布局。它会在加载xml
时创建,然后您可以用指定的视图层次结构替换ViewStub。我将使用不言自明的变量名,以避免其他说明:)。您可以在GitHub上检出sample project。
fragment_core.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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">
<ViewStub
android:id="@+id/child_fragment_will_be_displayed_here"
android:layout_width="match_parent"
android:layout_height="100dp">
</ViewStub>
<TextView
android:id="@+id/core_fragment_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/child_fragment_content_holder"/>
</RelativeLayout>
FragmentCore.class
public abstract class FragmentCore extends Fragment {
public FragmentCore() {
// Required empty public constructor
}
protected TextView mTextViewInCoreActivity;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View coreFragmentView = inflater.inflate(R.layout.fragment_core, container, false);
mTextViewInCoreActivity = coreFragmentView.findViewById(R.id.core_fragment_text_view);
loadLayoutFromResIdToViewStub(coreFragmentView, container);
return coreFragmentView;
}
public abstract void loadLayoutFromResIdToViewStub(View rootView,ViewGroup container);
}
fragment_child.xml
<FrameLayout
android:layout_width="match_parent"
android:layout_height="100dp"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/child_fragment_content_holder">
<TextView
android:id="@+id/child_fragment_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</FrameLayout>
FragmentChild.class
public class FragmentChild extends FragmentCore {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public void loadLayoutFromResIdToViewStub(View coreFragmentView, ViewGroup container){
setRetainInstance(true);
if (container != null) {
container.removeAllViews();
}
ViewStub stub = coreFragmentView.findViewById(R.id.child_fragment_will_be_displayed_here);
stub.setLayoutResource(R.layout.fragment_child);
stub.inflate();
TextView childFragmentTextView = coreFragmentView.findViewById(R.id.child_fragment_text_view);
mTextViewInCoreActivity.setText("Core (Parent) Fragment TextView is accessible");
childFragmentTextView.setText("Child Fragment TextView is accessible");
}
}
答案 5 :(得分:0)
您可以这样做
<i class="far fa-envelope" class="inbox"></i>
片段
abstract class BaseFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container:ViewGroup?, savedInstanceState: Bundle?): View {
return inflater.inflate(getContentView(), container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
onViewReady(savedInstanceState, arguments)
}
// create below 2 methods
abstract fun getContentView(): Int // this will be used to pass view
abstract fun onViewReady(savedInstanceState: Bundle?, bundle: Bundle?) // this will be invoked in our fragment when view is ready
}
答案 6 :(得分:0)
遵循这种简单干净的方法
public abstract class BaseFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(getLayoutId(), null);
return root;
}
@LayoutRes
protected abstract int getLayoutId();
}
就是基本片段了
然后获取子片段
public class ChildFragment extends BaseFragment {
@Override
protected int getLayoutId() {
return R.layout.child_fragment;
}
}
采用不同的方法来处理事情