考虑带有片段MainActivity
的活动MainFragment
。该片段具有一些复杂的布局层次结构和一个来自库Frame
的视图组com.framer:frame_me:1.1
。
如果我有两种foo
和bar
,我希望此Frame
仅在bar
风格而不在foo
中, XML元素java代码和依赖。我该怎么做?
我可以使用
编译依赖项barCompile 'com.framer:frame_me:1.1'
但是片段及其XML如何呢?我不想在两种风格中编写2个变体片段,因为我不想在2个地方保持相同的代码。
在我看来,一个可能的想法(可能是坏的想法)就是:
bar
源集中的单独文件中。在ViewStub
源集中添加具有相同名称的foo
元素。现在,在片段XML include
包含此XML文件
Frame
源集中的main
视图。在foo
源集和bar
源集中添加一个空实现。这样,所有逻辑都可以保留在bar
中,而所有常见逻辑都保留在main
源集中。这一切听起来只是为了编写特定于风味的代码和xml。
答案 0 :(得分:1)
如何用Frame
容器替换XML中的FrameLayout
标记?
然后在bar
风格的源代码中,您可以实例化Frame
并说出container.addView(frame)
。虽然foo
风格没有引用Frame
类,但会忽略容器。
这与您的第一种方法类似,但无需维护单独的资源集。这似乎是合理的,无论如何你都会有一些特定于风味的java代码。
答案 1 :(得分:0)
build.gradle sourceSets选项是什么? 您可以将Fragment和XML放在条形文件夹中,然后设置:
android {
productFlavors {
...
}
sourceSets {
bar.java.srcDirs = ['src/bar/java']
bar.res.srcDirs = ['src/bar/res']
}
}
答案 2 :(得分:0)
你只需要抽象。由于使用整数索引将资源标识到R类中,因此可以使用int变量作为布局文件的占位符,并且考虑到在活动布局中搜索布局元素ID的事实,可以回收公共元素。首先,创建一个包含所有常见元素的公共片段类:
public abstract class BaseFlavorFragment extends Fragment {
/*Define an interface for whatever code the fragment may need from the outside and a member for keeping reference of that. You can also use the host activity, this is just for flexibility*/
public interface whateverThisDoes{
void do();
}
/*All the common fragment members go here, as protected so you can reach them from every subclass*/
protected TextView title;
protected Button mainButton;
protected whateverThisDoes listener;
public void setWhateverThisDoes(whateverThisDoes listener){
this.listener = listener;
}
/*Finally, create a int variable that will hold the reference to the layout file you need to use. you will set this in every flavor using the setContainer method.*/
protected int layout = 0;
/*this will allow you to select which XML to use
layout = R.layout.flavorlayout*/
public abstract setContainer();
/*Use this method to inflate any flavor members, like the Frame you mentioned*/
public abstract void inflateComponents();
/*Use this to set listeners, data, or anything the flavor controls do*/
public abstract void setBehaviors();
/*Set here anything the common controls do*/
protected void setCommonBehaviors(){
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//whatever
}
});
setBehaviors();
}
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContainer();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(layout, container, false);
/*Inflate common components*/
title = (TextView) root.findViewById(R.id.title);
button = (Button) root.findViewById(R.id.button);
/*inflate flavor components, if there's any*/
inflateComponents();
/*assign data, listeners, whatever the flavor controls do*/
setBehaviors();
return view;
}
}
现在,您可以为Foo和Bar创建一个实现。如果唯一的区别是布局文件,将所有内容放入基类,并使用setContainer()设置布局文件。如果你有更多的差异,你只需要在每个抽象方法中处理它们。基类可以存在于每个风格的公共代码和实现中。如果您不需要从外部设置任何行为代码,则可以删除界面。