Change value in layout.xml conditionally in Android - android

I'm trying to get android:layout_marginEnd="-6dp" to change to 2dp conditionally in:
<FrameLayout
android:id="#+id/wifi_combo"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginEnd="-6dp"
>
My condition is:
if (mSignalClusterStyle == STYLE_ALWAYS) {
mMobileType.setVisibility(View.VISIBLE);
} else if (mWifiVisible) {
mMobileType.setVisibility(View.GONE);
}
I would like to add a line to the if statement that overrides the -6dp with 2dp in the xml file.
I have explored setMarginEnd(), but there are very few resources on this, seeing as it is only a year old, and I keep getting a compile error with it.
What is the best way to change android:layout_marginEnd on a condition programmatically?

FrameLayout layout = (FrameLayout) findViewById(R.id.wifi_combo);
FrameLayout.LayoutParams params = (LayoutParams) layout.getLayoutParams();
params.setMarginEnd(2);

The correct way to set the endMargin is using setMarginEnd() only, added in API 17.
http://developer.android.com/reference/android/view/ViewGroup.MarginLayoutParams.html#setMarginEnd(int)
BTW, what compile errors you are getting?

Related

Android Studio How To Set Constraints And Use LayoutParams Dynamically

In my Android Application I want to create a bunch of ConstraintLayouts where each has for example an ImageView and a TextView in them.
Everything is created from code exept for one TableRow with which I will start out. My Problem ist that despite being able to set the margins via LayoutParams for the ConstraintLayout, the ImageView and the TextView do not change at all when I try to set the margins.
public fun generateAsset(tableRow: TableRow) {
// <android.support.constraint.ConstraintLayout
// android:layout_margin="4dp"
// android:background="#drawable/x32_tile_dark">
val clayout = ConstraintLayout(context)
tableRow.addView(clayout)
val cparams = clayout.layoutParams as TableRow.LayoutParams
cparams.setMargins(4, 4, 4, 4) // <--- Works correctly!
clayout.layoutParams = cparams
clayout.setBackgroundResource(R.drawable.x32_tile_dark)
// <ImageView
// android:layout_width="0dp"
// android:layout_height="60dp"
// android:layout_marginTop="8dp"
// app:srcCompat="#drawable/x256_spaceship_door_gray_blue" />
val iView = ImageView(context)
clayout.addView(iView)
val iparams = iView.layoutParams as ConstraintLayout.LayoutParams
iparams.width = ConstraintLayout.LayoutParams.MATCH_PARENT
iparams.height = 200
iparams.setMargins(8, 8, 8, 8) // <--- Does not do anything!
iView.layoutParams = iparams
iView.setImageResource(R.drawable.x256_spaceship_door_gray_blue)
// <TextView
// android:text="Massive Spaceship Door"
// android:layout_marginLeft="8dp"
// android:layout_marginRight="8dp"
// android:layout_marginBottom="4dp"
// android:textColor="#android:color/white" />
val ntext = TextView(context)
clayout.addView(ntext)
val nparams = ntext.layoutParams as ConstraintLayout.LayoutParams
nparams.setMargins(8, 8, 8, 8) // <--- Does not do anything!
ntext.layoutParams = nparams
ntext.setTextColor(Color.WHITE)
ntext.text = assetName
}
The reason why this doesn't work is probably because I haven't set the constraints of the ImageView and the TextView but how do I do that in code?
The ImageView should be right in the center of the ConstraintLayout while the TextView is supposed to be in the center but at the bottom.
How can I set the constraints to do what I've described above?
You are right to suspect that not setting the constraints may be the issue. To set constraints programmatically take a look at ConstraintSet.
This class allows you to define programmatically a set of constraints to be used with ConstraintLayout. It lets you create and save constraints, and apply them to an existing ConstraintLayout.
As an added bonus, ConstraintSet permits the setting of margins while setting constraints.
There are some good tutorials online about how to use ConstraintSet.
Not 100% sure here, but i have a suggestion and believe you have to call
iView .updateMargins<ConstraintLayout.LayoutParama>{//do some stuff here}.
You probably ask "Why?".
Well, i think its because you already created val clayout = ConstraintLayout(context) but didnt specify which attributesSet it has, thus taking the default one. And since your View already has defaultParams, they need to be updated now.
But please do some independet reasearch or ask a real expert with real knowledge. Because i am not really sure and this is just some suggestion.

Error message text for TextInputLayout is cut off

Hey anyone know why this (see in the picture) happens?
It's happens for Xiaomi MiA1, while on Nokia 7.1 works fine.
My xml view layout
FrameLayout - root
ScrollView
RelativeLayout
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/til_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/profile.EMAIL"
android:theme="#style/TextInputLayoutTheme"
android:margin="16dp"
android:paddingBottom="8dp"
app:layout_constraintTop_toBottomOf="#+id/phone_wrapper"
>
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textEmailAddress"
android:textSize="16sp"
android:textColor="#color/darkTextColor"
android:imeOptions="actionDone"
tools:text="Email"
/>
</com.google.android.material.textfield.TextInputLayout>
I think that putting TextInputLayoutTheme is not relevant here, since I only manipulate with view's colors
The error message text gets cut off if you are setting the error on a TextInputLayout more than once.
So every time you are setting TextInputLayout error message text, just set it to null first.
textInputLayout.setError(null);
textInputLayout.setErrorEnabled(false);
textInputLayout.setError("Error Message");
Layout Inspector shows that even if there is some space for the error it doesn't draw view in all of it. Everything there is in LinearLayouts (and one simple FrameLayout) so there is no way something would overlap it, paddings are set to 0, there is no code changing height or something suspicious in the implementation, so I don't know what might be a reason of such behaviour.
Although I've found some solution which works. You need to find in TextInputLayout a view holding error (with id textinput_error) and add some small padding to it. I've done it by extending TextInputLayout and adding such code into init.
val errorTV = findViewById<TextView>(R.id.textinput_error)
errorTV.updatePadding(top = 4)
There is already issue on issue tracker - https://issuetracker.google.com/issues/116747167 so lets hope Google will fix it some day.
I resolved issue by saving and restore LayoutParams:
final ViewGroup.LayoutParams params = textInputLayout.getLayoutParams();
textInputLayout.setError(errorMessage);
textInputLayout.setLayoutParams(params);
I resolved issue by increasing size of error font to 14sp (orginal is 12sp)
<com.google.android.material.textfield.TextInputLayout
[...]
app:errorTextAppearance="#style/MyProfile.Error">
<style name="MyProfile.Error" parent="TextAppearance.Design.Error">
<item name="android:textSize">14sp</item>
</style>
Although as Shabbir Dhangot said I may be that setting TIL.setErrorEnabled(true) may help for some else.
As some have already pointed out, this is a known bug. See https://issuetracker.google.com/issues/116747167
I solved this by doing something like this (note that below code is Kotlin, so != works on Strings):
if(myInputLayout.error != error){
myInputLayout.error = error
}
I know it is not the best solution, but you can add a \n to the beginning of your error message.
For example, if your error is Error, just change it to \nError.
If you want to change the size of the \n you can use:
String newLine = "\n";
String errorMessage = "Error";
SpannableString spannableErrorMessage = new SpannableString(newLine + errorMessage );
spannableName.setSpan(new TextAppearanceSpan(activity, R.style.my_style),0,a.length(), 0);
spannableName.setSpan(new RelativeSizeSpan(2.0f), a.length(), a.length() + 1, 0);
You can use this Kotlin extension:
/**
* Fix a bug with [TextInputLayout] that cut the error text when setting the same text twice.
*/
fun TextInputLayout.setFixedError(errorTxt: CharSequence?) {
if (error != errorTxt) {
error = errorTxt
}
}
Usage:
yourTextInput.setFixedError("Your error text")

Android dataBinding - How to get resource id of a View in xml

In Android Studio my data binding itself works and is set up fine. I have a boolean defined like this:
<resources>
<bool name="showAds">false</bool>
</resources>
and in a layout.xml file i would like to referenced this boolean (which works fine) but i want to assign a id based on this boolean. Let me show you what i am trying to accomplish:
I have a button that is in a relativeLayout tag and depending on this boolean i would like to reposition the button. So I have this:
<Button
android:id="#+id/startButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="64dip"
****************
android:layout_below="#{#bool/showAds ? #+id/adone : #+id/title_main}"
****************
android:layout_centerHorizontal="true"
android:textColor="#0080FF"
android:text="#string/start_btn_title" />
See what i want to to do? I want to layout the button below a layout called adone if the showAds boolean is true, otherwise place it below a layout called title_main. Whats the syntax for this as what I have here is not compiling. I get a compile error:
expression expected after the second # sign
The above is the same problem as in How to get dimensions from dimens.xml
None of the LayoutParams attributes have built-in support. As answered in the linked article, data binding of LayoutParams was thought to be too easy to abuse so it was left out of the built-in BindingAdapters. You are not abusing it, so you should add your own.
#BindingAdapter("android:layout_below")
public static void setLayoutBelow(View view, int oldTargetId, int newTargetId) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)
view.getLayoutParams();
if (oldTargetId != 0) {
// remove the previous rule
layoutParams.removeRule(RelativeLayout.BELOW);
}
if (newTargetId != 0) {
// add new rule
layoutParams.addRule(RelativeLayout.BELOW, newTargetId);
}
view.setLayoutParams(layoutParams);
}
As an aside, the #+id/adone in the binding syntax will not create the id. You should create the id in the View you're binding to.

Hide included layout in android

I have to develop an android application.
I have created one layout file that uses another layout file using the include tag.
<include
android:id="#+id/footer"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
layout="#layout/footer_tabs" />
<include
android:id="#+id/footer1"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
layout="#layout/footertabs" />
I would like to show the included layout when a response is null, otherwise I would like to hide the layout and show the other. Here is what I have so far:
footertabs = (RelativeLayout) findViewById(R.id.footertab);
footer_tabs = (RelativeLayout) findViewById(R.id.footer_tab);
if (Constants.response==null) {
footertabs.setVisibility(View.VISIBLE);
footer_tabs.setVisibility(View.GONE);
}
else
{
footertabs.setVisibility(View.GONE);
footer_tabs.setVisibility(View.VISIBLE);
}
But I'm getting the following error:
07-15 17:19:09.893: E/AndroidRuntime(15143): Caused by: java.lang.NullPointerException
07-15 17:19:09.893: E/AndroidRuntime(15143): at com.example.androidbestinuk.HomePage.onCreate(HomePage.java:56)
Please help me debug this error.
you should change
footertabs = (RelativeLayout) findViewById(R.id.footertab);
footer_tabs = (RelativeLayout) findViewById(R.id.footer_tab);
with
footertabs = (RelativeLayout) findViewById(R.id.footer);
footer_tabs = (RelativeLayout) findViewById(R.id.footer1);
Well it appears to me that you're using the wrong id's. You're getting a null pointer somewhere (I'm not sure where because there are no line numbers), but I see in your xml you have id's, footer and footer1, but in your code you are trying to find elements with id's footertab, and footer_tab. You should make these id's match.
Using ViewBinding and Kotlin, it can be achieved this way
binding.yourInclude.root.visibility = View.GONE
For specific views inside <include> tag use code below
binding.yourInclude.textView.visibility = View.GONE

Android GraphView 2 without labels

I am currently trying to draw a graph within an Android application. The library I found is called GraphView (http://www.jjoe64.com/p/graphview-library.html). I am currently using version 2, which is available on GitHub.
Drawing graphs works really nicely. The code necessary to get a graph is the following:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Map<String,List<GraphEntry>> graphData = (...)
if (graphData != null) {
List<GraphEntry> entries = graphData.get("temperature");
GraphView.GraphViewData[] data = new GraphView.GraphViewData[entries.size()];
int i = 0;
for (GraphEntry entry : entries) {
data[i++] = new GraphView.GraphViewData(entry.getDate().getTime(), entry.getValue());
}
GraphView.GraphViewSeries graphViewSeries = new GraphView.GraphViewSeries("temperature", 0xffff0000, data);
LineGraphView graphView = new LineGraphView(this, "temperature");
graphView.addSeries(graphViewSeries);
graphView.setShowLegend(true);
LinearLayout graphLayout = (LinearLayout) findViewById(R.id.layout);
graphLayout.addView(graphView);
}
}
This will produce a normal graph. Unfortunately, all kinds of labels are missing. The documentation tells that for the normal use case, one does not have to care about labels, as the library does this automatically. What am I doing wrong? I only get the plain graph, without any labels.
For the completeness, I am adding the graph to a linear layout. The appropriate layout file has the following contents:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:padding="5dp"
android:id="#+id/layout"
android:orientation="vertical"
></LinearLayout>
The GraphEntry class is only a container with a java.util.Date attribute and a double value attribute.
Thank you very much for any help,
Matthias
I switched to another charting engine: AChartEngine. This one works out of the box.
I had the same problem. This can be solved by removing the following line from the manifest file.
android:theme="#style/AppTheme"
I know this is quite vague, but worked for me. I don't the exact reason why this happens. If u guys come across the better solution please do share it.
You should use the latest version from github and include that in your project. This will allow you to set various colours using
graphView.getGraphViewStyle().setGridColor(Color.GREEN);
graphView.getGraphViewStyle().setHorizontalLabelsColor(Color.YELLOW);
graphView.getGraphViewStyle().setVerticalLabelsColor(Color.RED);

Categories

Resources