I have a custom view (MyCustomView), in which I would like to add MvxSpinner and some TextView's. I would like to put all bindings on the custom view and pass them to the MvxSpinner, so I can integrate this new component in my application using the example below, using different bindings each time.
E.g.
in xml
<MyCustomView
android:width="match_parent"
android:height="match_parent"
local:MvxItemTemplate="#layout/item_spinner_dark"
local:MvxBind="ItemsSource StampTypes"
local:MvxDropDownItemTemplate="#layout/spinner_dropdown_item" />
Now, in code I want to add an MvxSpinner using the IAttributesof of MyCustomView
public class MyCustomView : MvxRelativeLayout
{
private MvxSpinner _spinner;
private TextView _errorTxt;
// A bunch of constructors
public MyCustomView (Context context, IAttributeSet attrs, IMvxAdapterWithChangedEvent adapter)
: base(context, attrs, adapter)
{
// Create an MvxSpinner with the attributes
// IMvxAdapterWithChangedEvent is always null
if(adapter == null){
_spinner = new MvxSpinner(context, attrs);
} else {
_spinner = new MvxSpinner(context, attrs, adapter);
}
// Add View to the Layout
AddView(_spinner);
// Add a TextView
_errorTxt = new TextView(context);
_errorTxt.SetPadding(8, 8, 8, 8);
_errorTxt.SetTextAppearance(context, Android.Resource.Attribute.TextAppearanceLarge);
_errorTxt.SetTextColor(Android.Graphics.Color.Red);
AddView(_errorTxt);
}
}
The code above compiles and runs, but the MvxSpinner is not populated with according to the local:MvxBind="ItemsSource StampTypes". When I remove the MyCustomView and use an MvxSpinner directly, all works as expected. Below is a screenshot of a normal MvxSpinner (which works like a charm) and the result of MyCustomView, where the MvxSpinner is not showing any items.
At first, I thought that creating the MvxSpinner using the IAttributes would do the trick. However, the IMvxAdapterWithChangedEvent parameter is null, so I ran off to try to create the Adapter myself. What am I missing?
Question:
So, how can I programatically create an MvxSpinner using these IAttributes?
NOTE: I'm extending from RelativeLayout, because when I extend from MvxSpinner I cannot add a TextView to the view.
I don't think you can do what you are trying to do using MvxRelativeLayout.
MvxRelativeLayout is supplied to allow you to bind collections of items inside a relative layout - it's not designed for you to manually insert items.
You might be able to achieve something that matches your "reusable control" requirements by:
using https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.Binding.Droid/Views/MvxFrameControl.cs - or by creating your own class similar to that control (based on RelativeLayout instead) - see the end of N=26 for more on this (http://mvvmcross.blogspot.co.uk/)
using an Android <include> block.
creating a custom Android control with C# properties which it forwards on to contained controls (see N=18 for an intro to custom controls)
Related
I'm trying to implement updated solution by Pedram from this answer, but I don't know to create a new instance of CircleProgressBar. It requires AttributeSet to be passed as a parameter, but how to get it?
CircleProgressBar circleProgressBar = new CircleProgressBar(MainActivity.this, ?);
The AttributeSet constructor is used when a view is inflated through a layout defined in XML. If you're constructing one in code, you should use the single argument constructor (e.g. new CircleProgressBar(MainActivity.this)). If the single-argument constructor is not defined, you just need to add it. You'll just need to add some getters/setters for the properties if you want to be able to construct it entirely from within Java code.
Alternately, just define a layout XML (example name view_progress_circle.xml) with a single item:
<com.your.packagename.CircleProgressBar
android:layout_width="100dp"
android:layout_height="100dp"
// etc. add other attributes here
/>
Then in code, create it with:
CircleProgressBar bar = (CircleProgressBar) LayoutInflater.from(MainActivity.this)
.inflate(R.layout.view_progress_circle, parent, false):
where parent is the ViewGroup you're going to attach the view to.
I know this is probably a very simple answer, but I'm a little stumped here. I'm creating a custom view, Panel, with the following constructor:
public Panel(Context context, AttributeSet attrs, int barLength){
super(context, attrs);
//paint object for drawing in onDraw
barPaint = new Paint();
bar = new Rect(3, 13, barLength, 3); // Rect object
//...other stuff, etc etc
}
In the activity where this view will be used, it will be created five different times within different cells of a table layout. Panel is a really simple Rect whose length will vary based on the argument barLength.
So, in the activity where the Panel views are actually created, they're called like so:
private Panel tagBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tagBar = (Panel) findViewById(R.id.custView);
}
As you can tell, this doesn't use the constructor I outlined above. How do I instantiate a new Panel, including properly passing it the right Context and AttributeSet? It seems now that when constructed (without int barLength as an argument) those just get passed in automatically. How should the tagBar be instantiated to properly pass it all three arguments?
To clarify, attrs.xml is a styleable attributes file that is mainly used to help set the colors of the bars from xml. Can anyone give me any direction?
Thanks!
If you have the panel class in the xml, the framework calls the proper constructor for you, passing it the Context and Attributes. You can then create a new attribute in attrs.xml, and once that's done you can pass the bar length via xml as well
<resources>
<declare-styleable name="Panel">
<attr name="barLength" format="int" />
</declare-styleable>
</resources>
Then in the xml just add barLength=n, just like you would any other attribute in the xml, but without android: in front of it.
Any one please guide me,
How to create a custom component in xml and java file
pass attributes from xml (this i somewhat completed)
how to pass attributes dynamically from new customClass() -- constructor method. -- i dont know how to implement this point
for Eg : I created a custom component with two textview as a single component. In xml i created two component by xml attributes. Now i want to create two new component by java code
by calling the constructor of my customClass.java I dont know how to create a new component dynamically from java code and how to display that in a view(Say a relative layout) Please help me provide any link or blog.
I have spent 1 week for this, But i didnt get any solution please help me
its very simple:
in your layout xml file simply put the following lines of xml code:
<com.example.project.MyComponent
android:id="#+id/myid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
Now, write a class named as your component:
public class MyComponent extends RelativeLayout {
public MyComponent(Context context, AttributeSet attr) {
super(context,attr);
}
#Override
public void onFinishInflate() {
// this is the right point to do some things with View objects,
// as example childs of THIS View object
}
}
Remember the constructor: this constructor is needed by the LayoutInflater to
find your component. And, dont forget to call super(...) when required.
You can do this by calling the constructor with context in its parameter and then setting the attributes with getter setters. You can find a good tutorial at Android tech point
MyComponent mycomponent = new MyComponent(context);
myComponent.setFirstTextView("text1");
myComponent.setSecondTextView("text2");
And then finally
layout.addView(myComponent);
android newbie here.
My first game involves a custom view, which is going to draw a game board and some scoreboards on the screen. I need to know how many players there are in order to get the number of scoreboards up, and I need this to be in known in the constructor of the custom view, so that appropriate variables are initialised on time.
My current implementation is like this, is this the correct way to get variables into the custom view constructor?...
I instantiate the custom view from my activity like this:
numPlayers=2;
setContentView(R.layout.gamescreen);
mBoardView = (BoardView) findViewById(R.id.board_view);
And in the custom view constructor:
public BoardView(Context context, AttributeSet attrs){
super(context, attrs);
vNumPlayers = ((GuappsXOMainGame)getContext()).getNumP();
That's how I have it now and it seems to work well enough, but is it better to be doing something along the lines of the answer to this question:?
android:how to instantiate my custom view with attributeset constructor
When a custom view (or SurfaceView) is the only view, often in games, then it is very easy to pass parameters like level, players, sound on etc by creating an instance of this view before setContentView(). An example:
MyView myView = new MyView(level, players, soundOn);
setContentView(myView);
In your case, your custom view is instantiated when the layout is created, hence you have to communicate back to the activity object to get the values. This is also possible. I have done this by setting static variables in the activity before calling setContentView(my_layout) then in the constructor for the custom view just say level = MyActivity.level
Or perhaps the way you are doing already where you obtain the instance of the activity and call a public method or variable.
In the link you provided an attribute is "hard-wired" into the XML layout. I don't see the advantage of that, when one can simply enter the value into the custom view class itself as a "final" variable.
I am new to android .can any one solve the following problem?
I just create the class like below .I need to know how to set property for the Edit text field
public class CustomEditText extends EditText{
public CustomEditText(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
}
Note: I mean the property like this
Edittext.setText("Demo");
Thanks in advance.
You need to create member variable and methods inside your CustomEditText.
Once you have them you can access it.
So there are a couple ways this can be interpreted and I will try to cover all of them.
EditText has multiple constructors. The one you have overridden requires that you as the developer set the properties in code for the rest of this instances usage. So you can actually just call setText(someString) from within this class or since the method is public call it directly on an instance of your class.
If you override the constructor that contains an attributeSet,
EditText(Context, AttributeSet)
You can use your component as part of an xml layout and set attributes on it there as if it were another EditText (as long as you call super(context, attributeSet). If you want to define your own custom attributes on top of that then that's actually quite neat how you do this.
In your project hierarchy, from the root you should either have or need to create a folder called "res/values" Within that folder a file named attr.xml should be created.
<declare-styleable name="myCustomComponents">
<!-- Our Custom variable, optionally we can specify that it is of integer type -->
<attr name="myCustomAttribute" format="integer"/>
...
<!-- as many as you want -->
</declare-styleable>
Now within your new constructor that makes use of the AttributeSet, you can read this new attribute, "myCustomAttribute".
public CustomEditText(Context context, AttributeSet set) {
super(context, set);
// This parses the attributeSet and filters out to the stuff we care about
TypedArray typedArray = context.obtainStyledAttributes(R.stylable.myCustomComponents);
// Now we read let's say an int into our custom member variable.
int attr = typedArray.getInt(R.styleable.myCustomComponents_myCustomAttribute, 0);
// Make a public mutator so that others can set this attribute programatically
setCustomAttribute(attr);
// Remember to recycle the TypedArray (saved memory)
typedArray.recycle();
}
Now that we have declared our new attribute and have setup code to read it, we can actually use it programatically or in an XML layout. So let's say you have an Xml layout in file, layout.xml
<ViewGroup
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res/com.my.apk.package"
>
...
<com.my.full.apk.package.CustomEditText
android:id="#+id/custom_edit"
...
custom:myCustomAttribute="12"
/>
...
</ViewGroup>
So in this we create a layout like normal, but notice we declare a new xml namespace. This is for your new component and your apk. So in this case "custom" is being used it will look inside your defined stylables for new parameters. By doing the previous steps with attr.xml, you have declared "myCustomAttribute" as a component attribute off of the http://schemas.android.com/apk/res/com.my.apk.package namespace. After that it's up to you to decide what attributes you would like to expose and what those attributes actually mean. Hope that helps.