How to android inflate XML Layout in ConstraintLayout class? - java

i create a ConstrantLayout class
public class AboutView extends ConstraintLayout {
TextView about_txt;
TextView dr_txt;
public AboutView(Context context) {
super( context );
init();
}
public AboutView(Context context, AttributeSet attrs, int defStyleAttr) {
super( context, attrs, defStyleAttr );
init();
}
private void init() {
LayoutInflater inflater = LayoutInflater.from( getContext() );
inflater.inflate( R.layout.about_layout,this );
about_txt = (TextView) findViewById(R.id.about_txt);
dr_txt = (TextView) findViewById(R.id.dr_txt);
}
}
Layout about_layout.XML file to inflate into class

Create layout how you want your custom view to look like. There is nothing complicated about it.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayoutxmlns: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"
xmlns:tools="http://schemas.android.com/tools">
<TextView
android:id="#+id/about_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
app:layout_constraintStart_toStartOf="parent"
tools:text="About" />
<TextView
android:id="#+id/dr_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
app:layout_constraintEnd_toEndOf="parent"
tools:text="Text" />
</android.support.constraint.ConstraintLayout>
This way you can set constraints and edit the layout with editor.
AFTER you are done with editting I would recommend changing the root view ConstraintLayout to merge.
By merging you won't have extra layout inside the custom view. Be careful - merge attributes are ignored.

Related

Edit Custom Views programmatically

I created a layout like this:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/rlMenu"
android:layout_centerHorizontal="true"
android:gravity="center"
android:layout_centerVertical="true">
<RelativeLayout
android:background="#drawable/dark_rectangle_bord"
android:id="#+id/rl1dia"
android:elevation="10dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_width="#dimen/sizeCard"
android:layout_height="#dimen/sizeCard"
android:layout_marginBottom="#dimen/padding_bottom_cards"
android:layout_marginEnd="#dimen/padding_end_cards"
android:layout_marginRight="#dimen/padding_end_cards"
android:layout_marginLeft="#dimen/padding_start_cards"
android:layout_marginStart="#dimen/padding_start_cards"
android:layout_marginTop="#dimen/padding_top_cards">
<TextView
android:text="1ยบ Dia"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tv1dia"
android:textStyle="normal|bold"
android:textColor="#color/Branco"
android:layout_alignParentBottom="true"
android:padding="10dp"
android:textSize="#dimen/texto_pequeno"
android:gravity="center"
android:fontFamily="sans-serif"
android:layout_centerHorizontal="true"/>
<ImageView
app:srcCompat="#drawable/ic_calendario_1"
android:id="#+id/iv1dia"
android:layout_width="#dimen/sizeImage"
android:layout_height="#dimen/sizeImage"
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true"
/>
After that, I had included it on my MainActivity.
<include
android:id="#+id/my_custom_view"
layout="#layout/custom_view></include>
But in this Custom View there are a RelativeLayout, a ImageView and a TextView. I need to create some Custom Views dynamically, sample as below.
How can i create this Custom View Programatically?
Ex.:
Button bt = new Button(MainActivity.this);
And how can I change the TextView, RelativeLayout, background and the ImageView programatically? Like:
CustomView cv = new CustomView(MainActivity.this);
cv.setImage(R.drawable.chips);
cv.setRlBackground(Color.WHITE);
cv.setText("Hello, World!");
You can use LayoutInflater for that
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View mView = (View) inflater.inflate(R.layout.custom_view, null);
View email = (View) mView.findViewById(R.id.email);
yourParentView.addView(mView);
But make sure when you add view to its parent call removeAllview() method of yourParentView
Maybe you want to create an actual custom View, using include will not create a custom View but will only inject in your layout that particular xml. So, create a class (in this case extends RelativeLayout but you can use whatever suits you here)
public class CustomView extends RelativeLayout {
private TextView textView;
private ImageView imageView;
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
inflate(context, R.layout.custom_view, this);
imageView = (ImageView) findViewById(R.id.image_view);
textView = (TextView) findViewById(R.id.text_view);
}
public void setImage(int resId){
imageView.setImageResource(resId);
}
public void setText(String text){
textView.setText(text);
}
}
an xml of the layout of your custom View (custom_view.xml), you might want to use merge instead of include since you already have a parent layout (RelativeLayout in this case)
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="#+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ImageView
android:id="#+id/image_view"
android:layout_width="48dp"
android:layout_height="48dp"
/>
</merge>
add your custom view to the Activity layout like this, please note that you need to use the full name of the custom View class you're using, in this case com.example.lelloman.dummy.CustomView
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<com.example.lelloman.dummy.CustomView
android:id="#+id/custom_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
and in your Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
CustomView customView = (CustomView) findViewById(R.id.custom_view);
customView.setImage(R.drawable.some_icon);
customView.setText("Hello world");
}

Custom Font in ListView

So I am trying to set a custom font (hello.ttf) which is already in the assets folder to a ListView. Below is my java and xml file.
faListFragment.java
public class faListFragment extends Fragment {
public faListFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_fa_list, container, false);
String[] faList = { "One",
"Two",
};
ListView listView = (ListView) view.findViewById(R.id.listFa);
ArrayAdapter<String> listviewAdapter = new ArrayAdapter<String>(
getActivity(),
android.R.layout.simple_list_item_1,
faList
);
listView.setAdapter(listviewAdapter);
// Inflate the layout for this fragment
return view;
}
}
and this is my fragment_fa_list.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.me.hello.faListFragment">
<!-- TODO: Update blank fragment layout -->
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/listFa" />
</FrameLayout>
I have tried several ways of adding the font, but cant quite seem to grasp how to go about it.
You have to create one layout xml in layout folder. In that layout xml you have to user custom textview with custom font.
For CustomTextView Link : Using custom font in android TextView using xml
ArrayAdapter<String> listviewAdapter = new ArrayAdapter<String>(
getActivity(),
R.layout.row_item, R.id.text ,
faList
);
listView.setAdapter(listviewAdapter);
Edit :
My CustomTextView Class
public class MyTextView extends TextView {
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyTextView(Context context) {
super(context);
init();
}
private void init() {
if (!isInEditMode()) {
Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "fonts/Roboto-Regular.ttf");
setTypeface(tf);
}
}
}
row_item.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:background="#00000000"
android:orientation="vertical">
<pakagename.MyTextView
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/title"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:text="CEO"
android:textColor="#000"
android:textSize="16dp" />
</RelativeLayout>

Android custom view background covering view content

I'm trying to figure out why an Android custom view which works when no background is set suddenly stops working when the background is set. It seems the background covers the items added to the view when it is set. I've simplified the view code to the bare minimum which reproduces the problem and to be able to post the code here. The custom view inherits from RelativeLayout and the code is as follow:
public class TestView extends RelativeLayout {
private LayoutInflater mInflater;
private ViewTreeObserver mViewTreeObserber;
private boolean mInitialized = false;
public TestView(Context ctx) {
super(ctx, null);
initialize(ctx, null, 0);
}
public TestView(Context ctx, AttributeSet attrs) {
super(ctx, attrs);
initialize(ctx, attrs, 0);
}
public TestView(Context ctx, AttributeSet attrs, int defStyle) {
super(ctx, attrs, defStyle);
initialize(ctx, attrs, defStyle);
}
private void initialize(Context ctx, AttributeSet attrs, int defStyle) {
mInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mViewTreeObserber = getViewTreeObserver();
mViewTreeObserber.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (!mInitialized) {
mInitialized = true;
drawItem();
}
}
});
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawItem();
}
private void drawItem() {
if (!mInitialized) return;
removeAllViews();
View item = mInflater.inflate(R.layout.testview_item, null);
TextView txt = (TextView)item.findViewById(R.id.test_view_item);
txt.setText("Test View Text");
txt.setTextColor(Color.BLACK);
txt.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
addView(item);
}
}
The item layout is simple:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal" >
<TextView
android:id="#+id/test_view_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:ellipsize="end"
android:maxLines="1" />
</LinearLayout>
And the sample app simply declares two instances of the custom view in XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin">
<TextView android:text="With Background set"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.machado.felipe.TestView
android:background="#android:color/holo_blue_light"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</com.machado.felipe.TestView>
<TextView android:text="WithOUT Background set"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.machado.felipe.TestView
android:layout_width="match_parent"
android:layout_height="wrap_content">
</com.machado.felipe.TestView>
</LinearLayout>
The result looks like the picture bellow:
This is driving me crazy! I'm not used to write custom views in android and this is someone else's code which I'm trying to fix! I don't even know if this is the way it should be done, since I'm inflating views and adding them to the RelativeLayout I don't think I should be adding them in the onDraw, but since the complete code is doing more complex stuff, as laying out the items in multiple rows with wrapping, it is possibly a valid approach... But, anyway, I can't figure out how to fix this!

Setting Nested TextView Text

I've created a layout for a button format I use multiple times. The button format has a TextView and an ImageView. With the way I'm including this layout in my main activity, I don't think I'm able to change the text of the inner TextView dynamically in Java or in the XML. Is there a different way I can do this such that I can set the text of the inner TextView?
Layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/settingslayout">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="25dp"
android:layout_marginTop="13dp"
android:textSize="20dp"
android:text="CHANGE ME"
android:id="#+id/text" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginRight="25dp"
android:layout_alignParentRight="true"
android:src="#drawable/left"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:maxHeight="30dp"
android:maxWidth="30dp"/>
</RelativeLayout>
Main Activity:
...
<include layout="#layout/settings_layout"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_below="#+id/accountStaticUnderline"
android:id="#+id/termBegin"
android:text="TEST" /> //DOESNT WORK
...
</RelativeLayout>
Setting the text that way won't work because android:text is not applicable to the <include> tag. More specifically, it's not applicable to the thing being included, which is a RelativeLayout. (You couldn't put the android:text on the RelativeLayout and have it apply to the TextView, nor would you expect that to work.)
My first suggestion (and the easiest immediate solution) is to use TextView's built in support for compound drawables so you can simply use TextViews instead of includes and have a style resource for the attributes you want.
If that's not good enough for your use case, then you might need to make a custom View. This view will replace the RelativeLayout and have the TextView and ImageView as children. The main thing to decide is where and how the children are created and their references are obtained: you can create them manually in Java when the parent is being constructed; or you can use some combination of layouts with <include>s and/or <merge>s. Making the text attribute work then requires some use of a <declare-styleable>.
I assume you want the children to always appear the same and that you want to reuse the layout you already made (i.e. you don't want to set all the attributes manually), so this is what I would probably do:
public class MyButton extends RelativeLayout {
private TextView mTextView;
private ImageView mImageView;
public MyButton(Context context) {
super(context);
init(context, null);
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
public MyButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attributeSet) {
LayoutInflater inflater = LayoutInflater.from(context);
inflater.inflate(R.layout.my_button, this, true); // used with merge tag
mTextView = (TextView) findViewById(R.id.text);
mImageView = (ImageView) findViewById(R.id.image);
int[] attrs = {android.R.attr.text};
TypedArray a = context.obtainStyleAttributes(attributeSet, attrs);
String text = a.getString(0, null);
mTextView.setText(text);
a.recycle();
}
}
In res/layout/my_button.xml:
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="25dp"
android:layout_marginTop="13dp"
android:textSize="20dp"
android:text="CHANGE ME"
android:id="#+id/text" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginRight="25dp"
android:layout_alignParentRight="true"
android:src="#drawable/left"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:maxHeight="30dp"
android:maxWidth="30dp"/>
</merge>
In your activity layout:
...
<!-- no more include -->
<com.package.MyButton
android:id="#+id/something"
android:layout_width="..."
android:layout_height="..."
android:text="..." />
<!-- you can have multiple instances with different IDs -->
<com.package.MyButton
android:id="#+id/something_else"
android:layout_width="..."
android:layout_height="..."
android:text="..." />
...
You could also use your own <declare-styleable> for the custom view, which will be necessary if later you want to have custom XML attributes for it, but the approach above should be sufficient.
sure, just type this code in your activity
((TextView)findViewById(R.id.text)).setText("enter_text_here");

Create custom layout in XML to initialize in code or in another layout xml

I have encountered an issue i am trying to resolve (or understand better the way it should be done) in creation of custom Layout in Android.
I want to create a custom RelativeLayout class for my use, which is defined in a layout XML file.
my_relative_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<com.mypackage.MyRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#null"
android:scaleType="fitStart"
android:src="#drawable/my_drawable"/>
<TextView
android:id="#+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/title_gray"
android:layout_below="#id/image_view"
android:gravity="center"
android:text="#string/placeholder" />
</com.mypackage.MyRelativeLayout>
Usage
public class MyRelativeLayout extends RelativeLayout {
private AttributeSet attrs;
private ImageView imageView;
private TextView textView;
public MyRelativeLayout(Context context) {
super(context);
}
public MyRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.attrs = attrs;
}
public MyRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.attrs = attrs;
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
if (attrs != null) {
TypedArray a = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.MyRelativeLayout, 0, 0);
drawableResource = a.getResourceId(R.styleable.MyRelativeLayout.image_view, 0);
a.recycle();
}
imageView = (ImageView) findViewById(R.id.image_view);
textView = (TextView) findViewById(R.id.text_view);
if (drawableResource != 0 && imageView != null) {
imageView.setImageResource(drawableResource);
}
}
}
My issue is that i want to initialise this layout both in another XML and in code.
But as I wrote my class and XML, i can only use it in code by doing:
myLayout = (MyRelativeLayout) LayoutInflater.from(this.getActivity()).inflate(R.layout.my_relative_layout, container, false);
When writing the following in another XML causes the onFinishInflate to fail on getViewById (returns null) and the childrenCount is 0
<com.mypackage.MyRelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="#id/another_layout"
app:image_view="#drawable/my_image" />
and doing the following, won't let me configure the custom image_view attribute.
<include layout="#layout/my_relative_layout"/>
To fix that, i can change the custom layout XML root element to be of type RelativeLayout and add the following to the beginning of onFinishInflate method:
LayoutInflater.from(getContext()).inflate(R.layout.my_relative_layout, this, true);
But the XML won't reference my class.
My questions are,
1. Am i missing something in the definition of the custom layout?
2. What is the correct definition for custom layout?
Thank you in advance!
First you should use the styled attributes in the contractor as shown in this example.
How can you expect from MyRelativeLayout that defined as fallow:
<com.mypackage.MyRelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="#id/another_layout"
app:image_view="#drawable/my_image" />
To be aware of views that are defined in my_relative_layout.xml?
To make it work you should create a costume layout and add it to com.mypackage.MyRelativeLayout manually.
Some thing like that:
costume_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#null"
android:scaleType="fitStart"
android:src="#drawable/my_drawable"/>
<TextView
android:id="#+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/title_gray"
android:layout_below="#id/image_view"
android:gravity="center"
android:text="#string/placeholder" />
</RelativeLayout>
Your costume view
public class MyRelativeLayout extends RelativeLayout {
private AttributeSet attrs;
private ImageView imageView;
private TextView textView;
public MyRelativeLayout(Context context) {
super(context);
init();
}
public MyRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(Context context){
LayoutInflater.from(context).inflate(R.layout.costume_layout, this);
}
}

Categories

Resources