(EDIT: problem fixed. See answer below)
I am stuck with this issue and it blocks a release so every help will be greatly appreciated.
Below is a trivial program that demonstrates the issue. I built it with the latest SDK (R19). It works well on gingerbread but fails on ICS. When the text size is increased (10 -> 30 -> 50) the text field height grows as expected but when the text size is reduced (50 -> 10), the text field has the full height, as if the text size is 50.
Anybody can reproduce it? Any suggestion for a workaround to make reduction in text size working properly?
Main activity:
package test.resize;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class ResizeTestActivity extends Activity {
private int mNextTextSize = 10;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final TextView textView = (TextView) findViewById(R.id.text0);
findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Cycle to next text size in {10, 30, 50}
textView.setText("Text Size " + mNextTextSize);
textView.append("\uFEFF"); // <--- THE FIX (see answer below)
textView.setTextSize(mNextTextSize);
// textView.requestLayout(); // does not help
// textView.invalidate(); // does not help
mNextTextSize = (mNextTextSize >= 50) ? 10 : (mNextTextSize + 20);
}
});
}
}
Main layout:
<?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="wrap_content"
android:orientation="vertical" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click To Cycle Text Size" />
<TextView android:id="#+id/text0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dip"
android:background="#ffffff00"
android:text=""/>
</LinearLayout>
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="test.resize"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".ResizeTestActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Answering my own question. Apparantly this is a reported bug.
http://code.google.com/p/android/issues/detail?id=22493
Adding
tv.append("\uFEFF"); // zero width space
after setting the TextView text solves the problem.
Note: if you are using custom font, make sure it contains the \uFEFF character. If not, you may also have problems with single line ellipsis.
Add textView.requestLayout() or textView.invalidate() after setting the new text size. I'm fairly certain one of those should do the trick.
Related
When using a Spinner with all default settings, I found some weird bugs when using the S Pen:
If you open the spinner and hover the S Pen at the bottom of the list, so it scrolls to the bottom, and then lift the S Pen up (so that the "hover circle" disappears), the list jumps back to the top
If you open the spinner and hover the S Pen at the bottom of the list, so it scrolls to the bottom, and then select an option, sometimes (intermittently - maybe about 1 in 4 times) it ignores the selected option and just jumps back to the top
I am testing on a tablet device in landscape orientation, the device is running Android 9 but I have done some tests on other devices and seems to be the same.
For comparison I tried using an app I use regularly which makes heavy use of spinners - "Packing List" by dotnetideas. This app was last updated in 2019 and has target SDK 27. You can easily test the spinners in the app by going into the settings and adding multiple items of luggage, then trying to edit the luggage on any packing list item. I found the S Pen works fine with this app, and it doesn't have the bugs described above, so there must be some way to work around it. That's not an open source app so I can't get ideas from their source code. I tried changing my target SDK to 27, but didn't make any difference.
Here is my code for what seems to me to be a completely vanilla implementation of spinner with all default settings - and still has these same "S Pen bugs" which are not reproducible in Packing List.
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.penpoc">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.SPenControlExperiment">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, MainFragment.newInstance())
.commitNow();
}
}
}
main_activity.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" />
MainFragment.java:
public class MainFragment extends Fragment {
public static MainFragment newInstance() {
return new MainFragment();
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.main_fragment, container, false);
Spinner spDefault = root.findViewById(R.id.spDefault);
ArrayAdapter<String> defaultSpinnerAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_item);
defaultSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spDefault.setAdapter(defaultSpinnerAdapter);
defaultSpinnerAdapter.addAll(getExampleList());
defaultSpinnerAdapter.notifyDataSetChanged();
return root;
}
private List<String> getExampleList() {
List<String> list = new ArrayList<>();
list.add("Alpha");
list.add("Bravo");
list.add("Charlie");
list.add("Delta");
list.add("Echo");
list.add("Foxtrot");
list.add("Golf");
list.add("Hotel");
list.add("India");
list.add("Juliet");
list.add("Kilo");
list.add("Lima");
list.add("Mike");
list.add("November");
list.add("Oscar");
list.add("Papa");
list.add("Quebec");
list.add("Romeo");
return list;
}
}
main_fragment.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainFragment">
<!-- Add some text views to push the spinner further down the page, this is not strictly necessary -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="one" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="two" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="three" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="four" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="five" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="six" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="seven" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="eight" />
<Spinner
android:layout_width="350dp"
android:layout_height="wrap_content"
android:id="#+id/spDefault" />
</LinearLayout>
Gradle deps:
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
I exactly faced the same problem with the S Pen. For an old app, API 25 Spinners were working great, but not any more with API 30. The only way I can resolve it was to replace Spinners by AutoCompleteTextViews. The drop down it generates seems to work correctly with the S Pen.
A few adaptations are needed to make it look like a Spinner:
1. Make AutoCompleteTextView not editable
From the documentation, you can make it by adding android:inputType="none". But, as said in MaterialAutoCompleteTextView code:
// Due to a framework bug, setting android:inputType="none" on xml has no effect. Therefore,
// we check it here in case the autoCompleteTextView should be non-editable.
So you have two options:
Set the input type programmatically autoComplete.setInputType(InputType.TYPE_NULL)
Use MaterialAutoCompleteTextView having a workaround for this
2. Handle clicks to show the drop down list
The default behavior with AutoCompleteTextView is to show suggestions by typing a few characters. So you have to force the drop down show when view gets focused.
autoComplete.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
autoComplete.showDropDown();
}
}
});
autoComplete.setOnDismissListener(new AutoCompleteTextView.OnDismissListener() {
#Override
void onDismiss() {
// Force focus change after selection
autoComplete.clearFocus()
}
});
3. Style the drop down list
Contrary to Spinner calling both getView() and getDropDownView() from Adapter, AutoCompleteTextView only calls getView(). So, to provide the correct view, you need to check the parent type in getView() call:
#Override
public #NonNull View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
// Workaround for AutoCompleteTextView using only this method
if (parent instanceof ListView) {
return getDropDownView(position, convertView, parent);
} else {
return super.getView(position, convertView, parent);
}
}
4. Style the AutoCompleteTextView
One last thing is to add the little caret at the end of the AutoCompleteTextView to make it look like a Spinner. You can use the android:drawableEnd attribute in your XML layout file to handle this.
5. Other tips
AutoCompleteTextView drop down list selection triggers AdapterView.OnItemClickListener instead of AdapterView.OnItemSelectedListener as Spinners do. Methods signatures are almost the same.
There is no proper way to trigger this listener for initial values. As a workaround, you can set the initial value, then attach listener and put your first validation logic in its constructor.
I'm fairly new in the android developing scene, however I have done a few dead simple applications to get an understanding of what the workflow would be like in the environment.
I'm having a difficulty running the example program called SimpleXYPlotExample and here's the code, manifest, main.xml and activity.java, respectively. I know this is a user error of some sort, but it would be great if someone could give me some helpful pointers as to what I'm doing wrong.
At first, all the code was broken, but I realized i forgot to import the library in. Now that I have done so, I try to run the program on my nexus s and it just crashes as it enters it.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="6"
android:targetSdkVersion="16"/>
<application android:label="SimpleXYPlotExample"
android:icon="#drawable/icon"
android:debuggable="true"
android:hardwareAccelerated="false">
<activity android:name=".MyActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
<?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"
>
<com.androidplot.xy.XYPlot
android:id="#+id/mySimpleXYPlot"
android:layout_width="fill_parent"
android:layout_height="150px"
android:layout_marginTop="10px"
android:layout_marginLeft="10px"
android:layout_marginRight="10px"
andsroidplot.title="A Simple XYPlot Example"
androidplot.ticksPerRangeLabel="4"
androidplot.ticksPerDomainLabel="2"
androidplot.gridPadding="4dp|4dp|4dp|4dp"
/>
</LinearLayout>
package com.example;
import java.util.Arrays;
import android.app.Activity;
import android.os.Bundle;
import com.androidplot.series.XYSeries;
import com.androidplot.ui.AnchorPosition;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.XLayoutStyle;
import com.androidplot.xy.XYPlot;
import com.androidplot.xy.YLayoutStyle;
public class MyActivity extends Activity
{
private XYPlot plot;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.mySimpleXYPlot);
// add a new series
XYSeries mySeries = new SimpleXYSeries(
Arrays.asList(0, 25, 55, 2, 80, 30, 99, 0, 44, 6),
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "series1");
plot.addSeries(mySeries, new LineAndPointFormatter(
getApplicationContext(), R.xml.f1));
// reposition the domain label to look a little cleaner:
plot.position(plot.getDomainLabelWidget(), // the widget to position
45, // x position value, in this case 45 pixels
XLayoutStyle.ABSOLUTE_FROM_LEFT, // how the x position value is applied, in this case from the left
0, // y position value
YLayoutStyle.ABSOLUTE_FROM_BOTTOM, // how the y position is applied, in this case from the bottom
AnchorPosition.LEFT_BOTTOM); // point to use as the origin of the widget being positioned
plot.centerOnRangeOrigin(60);
plot.centerOnDomainOrigin(5);
}
}
This may be contributed by the fact that the plot doesn't even show up on the graphical layout. This is what it looks like with this code:
http://imgur.com/qYl96Zi
As you can see, I have imported the androidplot library. Please advise.
The screenshot appears to be from the eclipse gui editor, which as the exception mentions does not support the setShadowLayer method and thus will not render. That's just a limitation with Eclipse and not a bug in your code or the library.
Normally to be able to answer questions regarding why Androidplot is crashing you'd need to supply the corresponding stack trace. I did however notice this typo in your xml:
andsroidplot.title="A Simple XYPlot Example"
As far as getting a working WYSIWYG editor my personal suggestion would be to give either IntelliJ IDEA or Android Studio (built on the current EAP version IntelliJ IDEA) a try. Both are free and both are in (IMHO) far superior IDE's.
I just installed the new Android Studio and am having some trouble as I follow the android developer training guide (http://developer.android.com/training/index.html).
Each time I try to compile my code, I receive this error
"Gradle: No resource identifier found for attribute 'android.onClick' in package 'android'"
My initial search resulted in me checking my API level and capitalization of onClick (neither of which seem to be the issue) ((I also understand that using onClick is not best practice, but I am simply following the guide at this point))
Since receiving this error, I have tried manually reinstalling gradle.
Does anyone know what my issue is?
Also, code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="horizontal" >
<EditText android:id="#+id/edit_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="#+string/edit_message" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/button_send"
android:android.onClick="sendMessage" />
</LinearLayout>
I suggest not to add button click listeners this way.
Button Click Listeners in Android
Check this out for more details. you can find plenty of resources on how to add buttons.
Generally i find it a good practice to add them through code as opposed to XML
try android:onClick="sendMessage"
In Activity, implement method public void sendMessage(View view);
You should add id to your view widget, and identify these views by id.
I agreed with DArkO. I had the same issue with Android Studio. When I use OnClickListener on my code, the issue has gone away.
On Activity.xml
<Button android:id="#+id/message_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/button_send"
/>
On Activity.java
Button button = (Button) findViewById(R.id.message_button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
sendMessage();
}
});
So I just started playing around with android and I'm trying to see what things I can do. I was following the very first android tutorial: http://developer.android.com/training/basics/firstapp/index.html and at the very end, you programmatically define a TextView. I wanted to change this to be defined in a new layout, so I wrote this (it is named display_message.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" >
<TextView android:id="#+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
And in the DisplayMessage class, I changed it to this:
public class DisplayMessage extends Activity {
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.display_message);
// Get message from intent
Intent intent = getIntent();
String message = intent.getStringExtra(FirstActivity.EXTRA_MESSAGE);
// Get the text view
TextView textView = (TextView) findViewById(R.id.text_view);
textView.setText(message);
}
}
However, Eclipse says that it doesn't know what R.layout.display_message is, nor does it know what R.id.text_view is. Is there somewhere else I need to define them or something? Where did I mess up?
It seems correct but be sure that the R class imported is the correct one.
Sometimes Eclipse imports android.R but the R file you need to import is your.package.name.R
I have been trying everything to get this to work, but to no avail. I tried to use the (AutoResizeTextView) posted here: Auto Scale TextView Text to Fit within Bounds
I created a new class file in my project with the name "AutoResizeTextView" and pasted the above code.
Then i opened the main.xml file and put n the following code:
<?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">
<com.mn.rl.AutoResizeTextView android:id="#+id/tv"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
in the mainActivity.java file, i have the following code:
package com.mn.rl;
import android.app.Activity;
import android.os.Bundle;
public class rlActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
com.mn.rl.AutoResizeTextView txt = (com.mn.rl.AutoResizeTextView) findViewById(R.id.tv);
txt.setText("Hello");
}
}
I have no errors in the code, and it runs but there is no autoresizing. the text remains the same size. in the xml i have the autoresize textview layout_width and layout_height set to fill parent, yet the font remains small. also tried txt.resize().
What am i doing wrong? Please Help.
there is a slight possibility that that class is only meant for resizing down. not up.