class CustomHeadersFragment : HeadersSupportFragment() {
I wand attach own layout for header in leanbag but But I can't find a code for it
Related
Consider an Activity MainActivity with a fragment MainFragment. The fragment has some complex layout hierarchy and a view group Frame which comes from a library com.framer:frame_me:1.1.
If I have 2 flavours foo and bar, and I want this Frame to be there only in bar flavour and not in foo, the XML element java code and dependency. How should I do this?
I can compile the dependency using
barCompile 'com.framer:frame_me:1.1'
But what about the fragment and its XML. I don't want to write 2 variations the fragment in both flavours because I don't want to maintain the same code in 2 places.
One possible idea (probably a bad one) in my mind is that this:
Move the XML element in a separate file in bar source set. Add ViewStub element in the foo source set with the same name. Now include this XML file using include in the fragment XML
Add an interface to handle Frame view in main source set. Add an empty implementation in foo source set and one in bar source set. This way all logic can remain in bar while all common logic remains in main source set.
This all sounds an awfully lot of work just to write flavour specific code and xml.
How about replacing the Frame tag in your XML with a FrameLayout container?
Then in the bar flavor's source code you can instantiate the Frame and say container.addView(frame). While the foo flavor will have no reference to the Frame class and will ignore the container.
This is similar to your first approach, but without having to maintain separate resource sets. And it seems reasonable, that you will have some flavor-specific java code anyway.
You just need abstraction. Since resources are identified using an integer index into the R class, you can use int variables as placeholders for the layout files, and given the fact a layout element ID is searched within the active layout, you can recycle the common elements. First, create a common fragment class, with all the common elements:
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;
}
}
Now, you can just create an implementation for Foo and Bar. if the only difference is the layout file, put everything into the base class, and set the layout file using setContainer(). If you have more differences you just need to deal with them into each abstract method. The base class can live into the the common code, the implementations, into each flavor. If you don't need to set any behavioral code from the outside, you can drop the interface.
what's about build.gradle sourceSets option ?
You could put Fragment and XML in bar folders and then set:
android {
productFlavors {
...
}
sourceSets {
bar.java.srcDirs = ['src/bar/java']
bar.res.srcDirs = ['src/bar/res']
}
}
In my current spring project, one of my activities should be a form where the user can insert a new entity. the code for the activity is like this:
public class FormNewItemActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.form_new_item_view);
Intent intent = getIntent();
Dao<?> dao = intent.getStringExtra(HelloActivity.EXTRA_MESSAGE);
}
}
the layout file should have a list of EditText fields and a unique Button in the end for trigger the saving of the data in a SQLite database.
I wonder if it's possible, giving a list of string with the name of the fields of the entity class, generate a xml layout file dynamically with one EditText for each field.
Anyone knows if this is really possible and how can be done?
You cannot dynamically create and load an XML layout file. However, what you can do is dynamically create the layout programatically which will have the same effect. This method works by creating and adding views at runtime to a layout that serves as a container - such as an empty LinearLayout. In your example you would make R.layout.form_new_item_view contain an empty LinearLayout
<LinearLayout
android:id="#+id/container_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
You would then find your container layout in onCreate
LinearLayout container = (LinearLayout) findViewById(R.id.container_layout);
And then create and add TextView or EditText as you needed from a list of field names
for(String title: listOfTitles){
TextView field = new TextView(this);
field.setText(title);
container.addView(field);
}
To customize the layout further you can set LayoutParams for each view added to control margins and other parameters.
I would like to improve the way i created the following UI. Currently i am creating each tablerow programmatically according to each object's type attribute.
class objectDTO {
private type; //enum
public boolean isMultiple(){...}
public boolean isSingle(){...}
}
I am trying to find a more dynamic solution like having a class for each type that might not requires programmatically adding layouts and components as i do in the fragment class,
if(objectDTO.isMultiple()) {
//Create TableRow + Multiple radiobuttons
}
else if(objectDTO.isSingle() {
//Create TableRow + Add One Checkbox
{
else {
//Create default invalid object Interface or skip
}
Havind a listadapter and applying the different ui there will just move the design problem to other class.
Early thanks for your contribution
Well, the simple solution for you would be to have a class hierarchy- a base objectDTO class and a child for each type. When you load the object list, have a factory method create the proper type of object. Each type would override a createView method which would create the view for that type. Then your table creation function becomes:
for(objectDTO object : allObjects){
View view = object.createView();
tableView.addView(view, lp);
}
But if you're creating a view for an object type, there's always going to need to be someone that dynamically creates view objects (createView in this case), and there's always going to need to be some function that knows what class to make an object (the factory in this case). Its just a matter of where you want that complexity to be.
I have separate file with listener.
I want to attach that listener to button, using xml Android:onClick, but after compilling i get error
01-11 14:35:35.560: E/AndroidRuntime(4682): java.lang.IllegalStateException: Could not find a method Btnlistener(View) in the activity class com.android.app.Activity for onClick handler on view class android.widget.Button with id 'btn1'
Is there any fancy way to import my listener class, in such way that i could use Android:onClick in xml.
Here is what I suggest:
Have a BaseActivity with the code for your listener, in a normal method
public void buttonClicked(View view) {
// put here what your listener did
}
And make all your activities that need this listener extends BaseActivity. You can define in your layouts the following xml element for buttons:
android:onClick="buttonClicked"
when you set onClick in xml then the activity class which inflate the xml must declare onClick event as a method, for example:
in XML:
onClick="btnAdd"
and in your activity:
public void btnAdd(View v){
//your code when the button click event is captured
}
There are quite a few questions about this subject, but could not find any with the specific problem I have...
In my layout.xml, I use the android:onClick tag for a Button to call the right onClickListener. I get the error :
java.lang.IllegalStateException: Could not find a method handle_cancel(View) in the activity class com.matthieu.HelloWorldApplication for onClick handler on view class android.widget.Button with id 'button_cancel'
I have that method implemented in the Activity, but it is looking for it in the class that extends Application... I don't understand why. The View and all that is setup only in the Activity.
If anyone needs, here is the declaration of that method (in my activity, NOT in HelloWorldApplication):
public void handle_cancel(View v) {
// do something useful here
}
Edit (from adamp request)... and probably answering my own question :
Here is part of the code where that layout is used...
public class AddVocabularyActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.top); // that layout contains an empty LinearLayout id/main_content
}
private some_other_function() {
LinearLayout main_content = (LinearLayout) findViewById(R.id.main_content);
main_content.removeAllViews();
View.inflate(getApplicationContext(), R.layout.hello, main_content); // layout.hello is the one containing the button
}
// some other stuff
}
While copy/paste this code, I am guessing the problem is that I used getApplicationContext to inflate the View with that Button...
As mentioned in my edit, changing the getApplicationContext() with the Activity context fixes it...
The convention works like this:
In the layout xml file, you give this attribute:
android:onClick:"methodname"
Then, inside a class, you define a method like this:
public void methodname(View v){
//your method code
}
Any other way of doing this is not documented. If you need parameters, just call another method inside that method.