I need every instance of a custom Button to use a FrameLayout as it's layout. How do I do this from my custom Button class, as to avoid having to wrap every xml defined CustomButton in a FrameLayout?
public CustomButton(Context context) {
super(context);
init(context);
}
public CustomButton(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public CustomButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
//this doesn't work...
FrameLayout layout = new FrameLayout(context);
inflate(context, R.layout.frame_layout, null);
}
just put your FrameLayout arount your Custom button in frame_layout and later in other xml you can put it in as and this view will be as it is in frame_layout
Related
Given a Button created at runtime:
Button button = Button(context)
The way to set a custom typeface is:
button.setTypeface(myTypeface)
However I find it only works before I add it to a ViewGroup and not after.
I've also tried:
button.setTypeface(myTypeface, myStyle)
but it didn't work either. I need to change my Button font dynamically. I've tried invalidate() and requestLayout() but the font never changes.
Solution:- you can subclass the Button class with your custom font and use it instead of button.
public class MyButton extends AppCompatButton {
public MyButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyButton(Context context) {
super(context);
init();
}
private void init() {
if (!isInEditMode()) {
Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "font.ttf");
setTypeface(tf);
}
}
}
I am trying to replace the text in a customized text view. the purpose is to force the text to be LTR; In order to do that, I am adding the "\u200E" prefix to my text.
Right now the setText() does not take any affect on the customized textView.
public class LocalizedTextView extends TextView {
public LocalizedTextView(Context context) {
super(context);
init(context);
}
public LocalizedTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public LocalizedTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
this.setText("\u200E" + getText().toString());
}
}
And this is the customized element:
<com.tempProject.customviews.LocalizedTextView
android:id="#+id/item_text"
style="#style/DrawerSectionText"
android:textDirection="ltr" />
Any Idea to force textView with RTL content to align to the left for devices older than 4.2.0, will be more than welcome.
The android:supportsRtl flag has to be set to true in the manifest.
I want to create a custom view a thing like a power switch ( a switch that switches between ON and OFF). When I have started to implement it I faced 3 constructors for View class:
public CusatomView(Context context) {
super(context);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
Now my question is: Which one of these constructors I should complete it to retrieve my own XML attribute (for instance: textOn and textOff)?
And what is the role of each?
Ideally, you should do your stuff in a separate method and call this from all three constructors, because you never know which of the constructor will be called. Here are the roles:
CusatomView(Context context) creates a new view with no attributes initialized.
CustomView(Context context, AttributeSet attrs) is invoked when you set attributes like layout_height or layout_width in your layout.xml
CustomView(Context context, AttributeSet attrs, int defStyle) is used when you set styles to your view.
You should create another funciton init and call it in all.
public CusatomView(Context context) {
super(context);
init();
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
The thing is any of this constructors can be used to instantiate your custom view. As in when you create a view in java code you just provide context and when it is created from xml attrs is also supplied.
Using the following code:
public class CustomView extends RelativeLayout {
public CustomView(Context context) {
this(context, null, 0);
}
public CustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView();
}
private void initView() {
inflate(getContext(), R.layout.custom_view, this);
}
}
The layout is simple:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/custom_view_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f00"/>
The hierarchyviewer shows the following:
The CustomView hierarchy is useless and I would like to remove it.
Is there a way to create a custom view extending a ViewGroup without adding that additional View?
If your CustomView is already a RelativeLayout in you XML layout you can just delete the RelativeLayout with "#+id/custom_view_id" and use as father the tag
That will merge the children with the CustomView without using an extra RelativeLayout.
The CustomView will setBackgroundColor
public class CustomView extends RelativeLayout {
public CustomView(Context context) {
this(context, null, 0);
}
public CustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView();
}
private void initView() {
setBackgroundColor(Color.parseColor("#f00"));
inflate(getContext(), R.layout.custom_view, this);
}}
and the layout xml file will be:
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<!-- children here -->
</merge>
I'm trying something like this
public class CustomViewSubclass extends HorizontalScrollView{
private LinearLayout layout;
public CustomViewSubclass(Context context) {
this(context,null,0);
}
public CustomViewSubclass(Context context, AttributeSet attrs) {
this(context,attr,0);
}
public CustomViewSubclass(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
layout = new LinearLayout(context);
}
// This is called from the `Activity`
public void startAsyncTask() { // code }
// This method is called in the `onPostExecute()` of an `AsyncTask` subclass
public void doSomething(Context context) {
ImageView image = ImageView(context);
layout.addView(image); // NullPointerException here, layout seems to be null
}
but it seems that layout on doSomething() is null. How is that even possible? I'm initializing it on the constructor... and I never re-initialize it again;
I'm adding my custom view via XML
<com.mypackage.CustomViewSubclass
android:layout_width="wrap_content"
android:layout_width="match_parent" />
Ok I fixed it, it was an stupid mistake made by me:
I used super() on the 3 methods, instead of using this().
public CustomViewSubclass(Context context) {
super(context,null,0);
}
public CustomViewSubclass(Context context, AttributeSet attrs) {
super(context,attr,0);
}
public CustomViewSubclass(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
layout = new LinearLayout(context);
}
Solution:
public CustomViewSubclass(Context context) {
this(context,null,0);
}
public CustomViewSubclass(Context context, AttributeSet attrs) {
this(context,attr,0);
}
public CustomViewSubclass(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
layout = new LinearLayout(context);
}