Extending RelativeLayout by inflating from xml? - android

I want to create a class named TabView which extends RelativeLayout and it is inflated from xml that contains RelativeLayout. The thing is that it doesn't seem to work as I expected. Did I do something wrong in the constructor? I know layoutInflater.inflate returns View object but what do I have to make it equal to? Any advice is apprecited!
private class TabView extends RelativeLayout {
private int mIndex;
public TabView(Context context) {
super(context, null, R.attr.vpiTabPageIndicatorStyle);
LayoutInflater layoutInflater = LayoutInflater.from(context);
layoutInflater.inflate(R.layout.tabview_title_subtitle, null);
}
public int getIndex() {
return mIndex;
}
public void setTitle() {
TextView title = (TextView)findViewById(R.id.title);
title.setText("Followers");
}
public void setSubitle() {
TextView subtitle = (TextView)findViewById(R.id.subtitle);
subtitle.setText("435");
}
}
The following is tabview_title_subtitle.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:text="Title"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#+id/title"
android:text="Subtitle"
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>

First, your layout should look like this:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:text="Title"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#+id/title"
android:text="Subtitle"
android:textAppearance="?android:attr/textAppearanceMedium" />
</merge>
In other way you'll end up with RelativeLayout that contains another RelativeLayout
Second. Inflate it like this:
layoutInflater.inflate(R.layout.tabview_title_subtitle, this);

You can see the following blog for creating and using custom views in android.
And probably using
inflater.inflate(R.layout.view_color_options, this, true);
instead of
layoutInflater.inflate(R.layout.tabview_title_subtitle, null);
is what you need to do.

Use:
layoutInflater.inflate(R.layout.tabview_title_subtitle, this);
to actually add the inflated view to TabView(right now you just inflate it and immediately discard it). Also if you want to use your custom view in a xml layout then also implement the constructor that takes a Context and an AttributeSet.

Related

Using TextView to inflate Layout

Upon clicking each TextView they should lead to another layout file to help the user learn about human trafficking. In the onCreate method I have setOnClickListener to my text view. Inflating it is an issue though. Is this called inflating a view? I've seen people recommending the use of fragments for this, using setContentView (from what I've found this shouldn't be used), and using the layout inflater while passing in the layout I want and null. However that doesn't work. How should this code look?
The XML:
<?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: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"
tools:context="com.example.piatt.worksafe.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Work Safe!"
android:textSize="36sp"
android:layout_centerHorizontal="true"
android:paddingBottom="32dp"
android:id="#+id/title"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="What is Human Trafficing?"
android:layout_below="#+id/title"
android:layout_centerHorizontal="true"
android:textSize="24sp"
android:padding="16dp"
android:id="#+id/whatIsHumanTrafficing"
android:clickable="true"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="How do I get safe labor?"
android:layout_below="#+id/whatIsHumanTrafficing"
android:layout_centerHorizontal="true"
android:textSize="24sp"
android:padding="16dp"
android:id="#+id/howDoIGetSafeLabor"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="How do I check that my job / job offer is legal?"
android:layout_below="#+id/howDoIGetSafeLabor"
android:layout_centerHorizontal="true"
android:textSize="24sp"
android:padding="16dp"
android:gravity="center"
android:id="#+id/checkLegality"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="How can I get help?"
android:layout_below="#+id/checkLegality"
android:layout_centerHorizontal="true"
android:textSize="24sp"
android:padding="16dp"
android:id="#+id/getHelp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="About us"
android:layout_below="#+id/getHelp"
android:layout_centerHorizontal="true"
android:textSize="16sp"
android:layout_alignParentBottom="true"
android:gravity="bottom"
android:id="#+id/aboutUs"
/>
</RelativeLayout>
The java class:
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView whatIsHumanTrafficing = (TextView) findViewById(R.id.whatIsHumanTrafficing);
whatIsHumanTrafficing.setOnClickListener(new View.OnClickListener(){
public void onClick(View view){
//What is this context, why do I need it and where does it come from?
//What is the ViewGroup, why do I need it and where does it come from?
view.inflate(Context context, R.layout.what_is_human_trafficing, ViewGroup root);
}
});
}
Aside: You could read the documentation for View.inflate
What is this context, why do I need it and where does it come from?
What: YourActivity.this (replace with your actual class name)
Why: You need it as a parameter to inflate a View.
What is the ViewGroup, why do I need it and where does it come from?
You probably don't need it; it can be null. It is the ViewGroup to inflate the View into. Like for a ListView, you would load each row into the list as the "group".
Anyways, if you want to dynamically show different layout file based upon what is clicked, yes Fragment's are one way to do that, and so are ViewStub's.
And you aren't actually calling inflate on the TextView because it is a static method. It is equivalent to doing this with a LayoutInflater
View v = LayoutInflater.from(YourActivity.this).inflate(R.layout.your_layout, null);
// TODO: Do something with v
The final code should look like:
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final RelativeLayout rl = (RelativeLayout) findViewById(R.id.splashScreenId);
TextView whatIsHumanTrafficing = (TextView) findViewById(R.id.whatIsHumanTrafficing);
whatIsHumanTrafficing.setOnClickListener(new View.OnClickListener(){
public void onClick(View view){
MainActivity.this.setContentView(R.layout.what_is_human_trafficing);
}
});
}
Set an on click listener to the text view then within it on MainActivity.this set the content view to the layout you want.

Can't type in EditText, even though it's focussed

When I click on the edittext it focuses, but I'm not able to type anything it. I have tried copying the XML edittext code into another activity and it worked fine, which suggests it's something to do with the java; but I have no idea what.
Code:
ap_overview_add.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="#+id/ap_overview_add_LL"
android:background="#drawable/ap_button_background"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add amount"
android:textSize="30sp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="15dp">
<EditText
android:layout_width="match_parent"
android:layout_height="40dp"
android:id="#+id/ap_et_add"
android:background="#drawable/edit_text_background"
android:inputType="numberDecimal"
android:padding="10dp"
android:drawableLeft="#drawable/pound_24dp"
android:backgroundTint="#color/abc_secondary_text_material_light"
android:imeOptions="actionSend"
android:lines="1"
android:maxLines="1"
android:singleLine="true"
android:layout_weight=".75"/>
<Button
android:layout_width="wrap_content"
android:layout_height="40dp"
android:id="#+id/ap_button_add"
android:text="Add"
/>
</LinearLayout>
</LinearLayout>
And I inflate this within a BaseAdapter, in the getView method like so:
public Integer[] mButtonIds = {
R.id.ap_overview_tab_LL,
R.id.ap_overview_add_LL,
R.id.ap_overview_rem_LL
};
public Integer[] mLayoutIds = {
R.layout.ap_overview_tab,
R.layout.ap_overview_add,
R.layout.ap_overview_rem
};
LinearLayout b;
View rootView;
LayoutInflater inflater;
inflater = LayoutInflater.from(mContext);
rootView = inflater.inflate(mLayoutIds[index], null);
b = (LinearLayout) rootView.findViewById(mButtonIds[index]);
return b;
And in the main activity class I have:
GalleryImageAdapter galleryImageAdapter;
galleryImageAdapter = new GalleryImageAdapter(this);
// Initializing the custom gallery //
gallery.setAdapter(galleryImageAdapter);

Android: Last line of textview cut off

I have a horizontal LinearLayout containing a TextView followed by a Spinner next to it. This LinearLayout is dynamically inflated multiple times in a fixed vertical LinearLayout contained within a RelativeLayout.
The problem is that since I switched from Theme.light to Theme.holo.light, the last line of the TextView gets cut in half. This happens when the dynamic text is long and spans more than one row.
I have been able to fix this by adding bottom padding to the horizontal LinearLayout containing the TextView and Spinner.
This does not feel like a fix, but more of a hack. Can someone please give me some advice on how to properly fix this?
I have also read some other questions, but none seem to help.
Horizontal Linear layout:
<?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:orientation="horizontal">
<TextView
android:id="#+id/textView1"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginRight="20dp"
android:text="TextView"/>
<Spinner
android:id="#+id/spinner1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Relative layout where above layout is dynamically inflated at Linear Layout with id ll2_7:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ScrollView
android:id="#+id/scrollView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/relLayoutButtonNext"
android:layout_below="#id/textView1" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="20dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp" >
<TextView
android:id="#+id/textView10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="30dp"
android:text="2.7" />
<TextView
android:id="#+id/textView11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_toRightOf="#id/textView10"
android:text="#string/question2_7" />
<LinearLayout
android:id="#+id/ll2_7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView11"
android:layout_below="#+id/textView11"
android:orientation="vertical" android:layout_marginBottom="20dp">
</LinearLayout>
</RelativeLayout>
</ScrollView>
</RelativeLayout>
EDIT:
Here is the complete layout xml for above:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/textView1"
style="#style/question_section_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="#string/question2_header" />
<RelativeLayout
android:id="#+id/relLayoutButtonNext"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#color/bottomBar"
android:paddingBottom="3dp"
android:paddingLeft="50dp"
android:paddingRight="50dp"
android:paddingTop="3dp" >
<Button
android:id="#+id/buttonNext"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:onClick="nextStep"
android:text="Next Section"
android:textSize="20sp" />
<Button
android:id="#+id/buttonPrevious"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:onClick="previousStep"
android:text="Previous Section"
android:textSize="20sp" />
</RelativeLayout>
<ScrollView
android:id="#+id/scrollView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/relLayoutButtonNext"
android:layout_below="#id/textView1" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="20dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp" >
<TextView
android:id="#+id/textView10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="30dp"
android:text="2.7" />
<TextView
android:id="#+id/textView11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_toRightOf="#id/textView10"
android:text="#string/question2_7" />
<LinearLayout
android:id="#+id/ll2_7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView11"
android:layout_below="#+id/textView11"
android:orientation="vertical" android:layout_marginBottom="20dp">
</LinearLayout>
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView10"
android:layout_below="#+id/ll2_7"
android:text="2.8" />
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/ll2_7"
android:layout_toRightOf="#+id/textView10"
android:text="#string/question2_8" android:layout_marginBottom="10dp"/>
<LinearLayout
android:id="#+id/ll2_8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView3"
android:layout_below="#+id/textView3"
android:layout_marginBottom="20dp"
android:orientation="vertical" >
</LinearLayout>
<TextView
android:id="#+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView2"
android:layout_below="#+id/ll2_8"
android:text="2.9" />
<TextView
android:id="#+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/ll2_8"
android:layout_toRightOf="#+id/textView10"
android:text="#string/question2_9" android:layout_marginBottom="10dp"/>
<LinearLayout
android:id="#+id/ll2_9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView5"
android:layout_toRightOf="#+id/textView10"
android:orientation="vertical" android:layout_marginBottom="20dp">
</LinearLayout>
<TextView
android:id="#+id/textView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView4"
android:layout_below="#+id/ll2_9"
android:text="2.10" />
<TextView
android:id="#+id/textView7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/ll2_9"
android:layout_toRightOf="#+id/textView10"
android:text="#string/question2_10" android:layout_marginBottom="10dp"/>
<LinearLayout
android:id="#+id/ll2_10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView7"
android:layout_marginBottom="20dp"
android:layout_toRightOf="#+id/textView10"
android:orientation="vertical" >
</LinearLayout>
<TextView
android:id="#+id/textView8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView6"
android:layout_below="#+id/ll2_10"
android:text="2.11" />
<TextView
android:id="#+id/textView9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/ll2_10"
android:layout_toRightOf="#+id/textView10"
android:text="#string/quesiton2_11" android:layout_marginBottom="10dp"/>
<LinearLayout
android:id="#+id/ll2_11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView9"
android:layout_below="#+id/textView9"
android:orientation="vertical" android:layout_marginBottom="20dp">
</LinearLayout>
<TextView
android:id="#+id/textView12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView8"
android:layout_below="#+id/ll2_11"
android:text="2.11.1" />
<TextView
android:id="#+id/textView13"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/ll2_11"
android:layout_toRightOf="#+id/textView10"
android:text="#string/question2_11_1" android:layout_marginBottom="10dp"/>
<LinearLayout
android:id="#+id/ll2_11_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView13"
android:layout_toRightOf="#+id/textView10"
android:orientation="vertical" android:layout_marginBottom="20dp">
</LinearLayout>
</RelativeLayout>
</ScrollView>
</RelativeLayout>
I applied a LayoutGravity to the TextView item:
android:layout_gravity="fill"
I've encountered the same cut-off issue as shown at the screenshot. It is caused by the baseline alignment in the horizontal LinearLayout. TextView and Spinner have different baselines due to font size difference. To fix the issue it is needed to disable baseline alignment for the layout by setting:
android:baselineAligned="false"
or in the code:
layout.setBaselineAligned(false);
I had the same problem, and found that simply adding
android:includeFontPadding="false"
the final line of text no longer had its descenders clipped.
I added some dummy space after text by adding
textView.setText(firstString+"\n");
I tried all other solution.But this was the only solution worked for me
I found a different solution by extending TextView and adding a custom Class like this:
public class AdaptingTextView extends TextView {
public AdaptingTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public AdaptingTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AdaptingTextView(Context context) {
super(context);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// set fitting lines to prevent cut text
int fittingLines = h / this.getLineHeight();
if (fittingLines > 0) {
this.setLines(fittingLines);
}
}
}
Put the problematic textview inside a framelayout. I think the text view is not calculated correctly because of the sibling view, Spinner.
<?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:orientation="horizontal">
<FrameLayout
android:layout_width="150dp"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textView1"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginRight="20dp"
android:text="TextView"/>
</FrameLayout>
<Spinner
android:id="#+id/spinner1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
When this occurs, you should ensure that the TextView is not growing larger than it's container -
If a TextView is set to wrap_content and it's container (or an ancestor container) doesn't leave room for the TextView to grow into it can be occluded.
If that's not the case, it's also possible the onMeasure() of the TextView sometimes doesn't correctly measure the tails of letters, non-latin characters or the effects from text being italic. You can correct for this by setting a global style for your TextView so it will be picked up without needed to change your entire code base:
Ensure that you're application/activities use a custom theme like so:
<style name="Custom" parent="#android:style/Theme.Light">
<item name="android:textViewStyle">#style/Custom.Widget.TextView</item>
</style>
<style name="Custom.Widget.TextView" parent="#android:style/Widget.TextView">
<item name="android:gravity">fill</item>
<item name="android:padding">1sp</item>
</style>
The answer by #Rynadt was really helpful in getting to the above stage. Setting the gravity of the Text inside the View ensures on some devices that occlusion never takes place (The text is correctly fitted inside the view), on others a helping hand with padding of an sp value, ensures that the tails et al are accounted for with a TextSize specific value.
My solution was close to the accepted one, but I had to change it to
android:layout_gravity="fill_vertical"
instead. Otherwise the other rows would have been stretch as well with added line breaks at random places. For example, the biggest row had 4 lines, so another row was changed from
this is a testphrase
to
thi
s is
a testph
rase
try with removing android:paddingBottom="20dp"
from
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="20dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp" >
getViewTreeObserver().addOnGlobalLayoutListener does not work in a recycler view. If you're using a recycler, use View.addOnLayoutChangeListener:
I found that the ellipsizing I defined for textView in xml was not always reflected so I programmatically set it before reassigning the text property. This worked for me.
textView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
#Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
textView.removeOnLayoutChangeListener(this);
float lineHeight = textView.getLineHeight();
int maxLines = (int) (textView.getHeight() / lineHeight);
if (textView.getLineCount() != maxLines) {
textView.setLines(maxLines);
textView.setEllipsize(TextUtils.TruncateAt.END);
// Re-assign text to ensure ellipsize is performed correctly.
textView.setText(model.getText());
}
}
});
If you have this problem and your TextView is inside a RelativeLayout, try switching the RelativeLayout for a LinearLayout.
That fixed the problem for me
You can use a global layout listener for a TextView in any type of ViewGroup.
final TextView dSTextView = (TextView)findViewById(R.id.annoyingTextView);
dSTextView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
dSTextView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
float lineHeight = dSTextView.getLineHeight();
int maxLines = (int) (dSTextView.getHeight() / lineHeight);
if (dSTextView.getLineCount() != maxLines) {
dSTextView.setLines(maxLines);
}
}
});
You can read more about it here
I know it's so late, but this is work like charm for me.
add this code to your textview
android:ellipsize="marquee"
android:layout_weight="1"
I think there is very little you can do to get this working by altering the layouts. As I have found that some methods work only in some cases. I think it depends on the entire layout hierarchy and is not a one-size-fits-all solution. I have also noticed that it happens especially when you have a different font that you want to set to the TextView.
A sure shot method that I have experimented and tested is that you can set the font attributes in code after the view is inflated. I am assuming that you have a font in the assets/fonts folder that you want to you.
For eg in a Fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.fragment_view, container, false);
TextView tv = (TextView)view.findViewById(R.id.text_view);
tv.setText("Insert text that needs to be displayed");
AssetManager assetManager = getContext().getAssets();
Typeface typeFace = Typeface.createFromAsset(assetManager, "Fonts/OpenSans-Light.ttf");
tv.setTypeface(typeFace , 0); // 0 is normal font
tv.setPadding(10, 0, 10, 0); // This is not mandatory
}
And in an Activity:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(Resource.Layout.main_activity);
TextView tv = (TextView)this.findViewById(R.id.text_view);
tv.setText("Insert text that needs to be displayed");
AssetManager assetManager = getContext().getAssets();
Typeface typeFace = Typeface.createFromAsset(assetManager, "Fonts/OpenSans-Light.ttf");
tv.setTypeface(typeFace , 0); // 0 is normal font
tv.setPadding(10, 0, 10, 0); // This is not mandatory
}
I have this same problem, and its very annoying.
It only happens with Arabic text.
If you make the label multi-line and adding a \n at the end of your string, it would fix it, but the problem is that there would be a big gap between this label and the object below it, due to the fact that this field now has a new empty line below it.
A custom control can be done to get around that. But overall, this is an annoying bug.
Best workaround for this is to add a dummy View of desired height (i.e. this will add padding itself) at the bottom of your view.
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp" >
<View
android:layout_width="match_parent"
android:layout_height="30dp"/>
</TableRow>
Like in my case I added one more table row at the bottom of the view. Hope this could help someone.
Add padding to the bottom of the text view:
android:paddingBottom="24dp"
I had the same problem and found a handy solution. I get the number of lines of the TextView after rendering and set the height according to the number of lines. Here is the code.
TextView textView = (TextView) layout.findViewById(R.id.textView);
textView.setText(this.text);
textView.post(new Runnable() {
#Override
public void run() {
int linesCount = textView.getLineCount();
textView.setLines(linesCount);
}
});
For me, this solution worked like a charm.
The height and width of my outermost layout was set dynamically, so the TextView contained within got it's text cut even if I set android:maxLines in my xml (for different devices it was behaving differently).
After trying out different methods, finally I got a solution that fixed my issue.
Textview:
public class CustomTextView extends androidx.appcompat.widget.AppCompatTextView {
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomTextView(Context context) {
super(context);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// set fitting lines to prevent cut text
int fittingLines = h / this.getLineHeight();
if (fittingLines > 0) {
this.setLines(fittingLines);
this.setEllipsize(TextUtils.TruncateAt.END);
}
}
}
xml:
<com.myproject.android.customviews.CustomTextView
android:id="#+id/tv_partner_description"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="top"
android:textColor="#color/white"
android:textSize="#dimen/text_small_medium" />
create theme as for particular language like style-ar which cut-off textview:
<style name="EnnodaCustomTextView" parent="Widget.AppCompat.TextView">
<item name="android:paddingTop">1dp</item>
<item name="android:paddingBottom">1dp</item>
</style>
Apply it in you AppTheme to reflect in overall app for padding bottom, as :
<item name="android:textViewStyle">#style/EnnodaCustomTextView</item>
Note : create same style name in default styles.xml with no item tags for padding..(where no need of extra padding )
I finally fixed it!
I try to add String to the TextView in Service and then call scrollTo(), the last line be cut off!
The scrollTo() should be call in "Runnable", like:
private ScrollView mScrollView;
public void scrollToBottom()
{
mScrollView = (ScrollView) findViewById(R.id.debug_textview_scrollview);
mScrollView.post(new Runnable()
{
public void run()
{
mScrollView.fullScroll(View.FOCUS_DOWN);
}
});
}
I think it because in the monent of call scrollTo() in service, the update of TextView is not ready.

Accessing the Custom View in android

I am trying to create a icon and a short description below it. I have created a customised View class with a ImageView and a TextView and i integrated it with my xml file, now the imageView and the default text appears in the screen,i don't know how to change the text content of the textview or the source of the imageview.
MyView.java
package sda.jk;
public class MyView extends LinearLayout{
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
LayoutInflater li=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v= li.inflate(R.layout.myview, this);
}
}
myview.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/ic_launcher"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="my view"/>
</LinearLayout>
main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/sda.jk"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<sda.jk.MyView
android:id="#+id/myView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</sda.jk.MyView>
</LinearLayout>
Step-1 First assign id to image view and text view in myview. xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/myImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/ic_launcher"
/>
<TextView
android:id="#+id/myText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="my view"/>
</LinearLayout>
Step-2
initialize your own view in oncreate method using
MyView mv = (MyView)findViewById(R.id.myView1);
step-3
initilize image view and text view using findViewById method of your own view
TextView textView = (TextView) mv.findViewById(R.id.myText);
ImageView imageView = (ImageView) mv.findViewById(R.id.myImage);
step-4
set text to text view using setText method
textView.setText("Sunil Kumar Sahoo");
set background image to image view using
imageView.setBackgroundResource(R.drawable.ic_launcher);
Your oncreate method will be like the following (from step-2 to step-4)
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MyView mv = (MyView)findViewById(R.id.myView1);
TextView textView = (TextView) mv.findViewById(R.id.myText);
textView.setText("Sunil Kumar Sahoo");
ImageView imageView = (ImageView) mv.findViewById(R.id.myImage);
imageView.setBackgroundResource(R.drawable.ic_launcher);
}
You write a function in sda.jk.MyView for setting text. For changing text, just call the function with a string parameter
Class MyView extends LinearLayout
{
//...
public void setUserText(String str)
{
textview.setText(str);
}
//...
}
You can add custom attributes by writing a custom attr.xml and loading the attributes in your custom view's constructor. For a full example check this page
http://javawiki.sowas.com/doku.php?id=android:custom-view-attributes
There is a useful feature in TextView called compund drawables, which allows you to incorporate a drawable to be drawn above, below, left or right of your text.
use it like so:
<TextView
android:id="#+id/txt"
android:text="my compound drawable textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="#drawable/xxxxx" />
you can use drawableBottom, drawableLeft etc.. as well.
this way you don't need to implement your own class.
For accessing individual elements from a View hierarchy, use the findViewById method. Refer to http://developer.android.com/reference/android/view/View.html#findViewById%28int%29
You would have to provide identifiers to your view elements in your XML thus:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/imgView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/ic_launcher" />
<TextView
android:id="#+id/txtView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="my view" />
</LinearLayout>
and refer them from your custom view class thus:
ImageView imageView = (ImageView)v.findViewById(R.id.imgView);
TextView textView = (TextView)v.findViewById(R.id.txtView);
Typically, you would like to keep the views as instance variables (members) so that you can change them from other methods.

Setting a layout to use as empty view for a ListView in case adapter has zero items in a Activity

How to use a layout as empty view for a listview when the adapter has zero elements?
setEmptyView is not working with this code :
public class ZeroItemListActivity extends Activity {
private ArrayList<String> listItems=new ArrayList<String>();
private ListView mMyListView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mMyListView=(ListView) findViewById(R.id.MyListView);
mMyListView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,listItems));
LayoutInflater inflator=getLayoutInflater();
View emptyView=inflator.inflate(R.layout.empty_list_item, null);
//Empty view is set here
mMyListView.setEmptyView(emptyView);
}
public void addItem(View v){
listItems.add("list Item");
mMyListView.invalidate();
}
}
Layouts used : empty_list_item.xml
<?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">
<Button android:id="#+id/Button01" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Empty List,Click to add items"></Button>
</LinearLayout>
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="#string/hello" />
<ListView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/MyListView"></ListView>
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/AddItemsButton"
android:text="Add Items" android:onClick="addItem"></Button>
</LinearLayout>
The easiest way to get this done is to put the empty view in the main.xml layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello" />
<ListView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/MyListView">
</ListView>
<!-- empty view -->
<LinearLayout android:id="#+id/emptyView"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button android:id="#+id/Button01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Empty List,Click to add items">
</Button>
</LinearLayout>
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/AddItemsButton"
android:text="Add Items"
android:onClick="addItem"></Button>
</LinearLayout>
Then, in your code, set your empty view like this:
mMyListView.setEmptyView(findViewById(R.id.emptyView));
The reason your code isn't working is that the ListView and Empty view need to be in the same view heirarchy. And your call to inflate pass null as the parent so they are in different heirarchies.
The Android Dev tutorial for List Activity covers this topic:
http://developer.android.com/reference/android/app/ListActivity.html
Basically have your class extend ListActivity. Set your list id to #id/android:listand the "empty view" id to #id/android:emptyin the same XML layout.
Hope this helps :)
When, inflating the view, you have to set the view parent to be part of the Layout hierarchy rather than pass null in some cases.
Replace
View emptyView = inflator.inflate(R.layout.empty_list_item, null);
with
View emptyView = inflator.inflate(R.layout.empty_list_item, (ViewGroup) mMyListView.getParent());
then you set the empty view as you did before with.
mMyListView.setEmptyView(findViewById(R.id.emptyView));

Categories

Resources