Create custom preference - android

I would like to create a SeekBarPreference like preference. I needed range Seekbar. Then I found this library: https://github.com/syedowaisali/crystal-range-seekbar . I would like to create a preference using CrystalRangeSeekbar that will have same look as other preferences.
I use compileSdkVersion = 29, minSdkVersion = 23, targetSdkVersion = 29.
Is that even possible on Android? I spent several hours trying to code something, but I never managed to get same look. I need all padding, margins, caption and summary positions, etc. to be same as in built-in preferences.
Is there any official manual to make custom preferences that will have same look as built-in preferences?

I don't think there is a manual on how to do this, but I had a problem where I needed a ranged seekbar preference for minSdkVersion=22 and what was available at the time did not allow a ranged seek until a later SDK version.
So I just made my own, not sure how exactly it looks compared to the built in preferences
The xml layout snippet is used is
<GridLayout
android:id="#+id/GridLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="2"
android:orientation="horizontal">
<SeekBar
android:id="#+id/fontSeek"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="0"
android:layout_columnWeight="15"
android:layout_gravity="fill"
android:max="40"
android:padding="6dp"/>
<TextView
android:id="#+id/fontText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="1"
android:layout_gravity="center"
android:textStyle="bold"
android:textColor="#color/colorText"
android:typeface="monospace"
android:minEms="2"
android:padding="6dp"/>
</GridLayout>
then in the code I adjusted the textview value to show the adjusted range instead of 0 to 40 by adding 20 to the value.
The extracted Java code associated with xml
int fontSize;
int fontSizeOffset = 20;
fontSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// Work out the correct values
fontSizeAdjusted = progress;
fontSize = fontSizeAdjusted + fontSizeOffset;
// Update the Textview
fontTextView.setText(String.valueOf(fontSize));
// store pref
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt("fontSize", fontSize);
editor.apply();
}
public void onStartTrackingTouch(SeekBar seekBar) {
// Do Nothing
}
public void onStopTrackingTouch(SeekBar seekBar) {
// Do Nothing
}
});
You might be able to do better now with Androidx https://developer.android.com/reference/androidx/preference/SeekBarPreference but this was not available when I developed this code.
You should be able to tweak the style to match exactly the standard preference as the docs say it is just a seekbar with optional texview.
You can always look at the source for Androidx to see how they do it e.g. https://android.googlesource.com/platform/frameworks/support/+/refs/heads/androidx-master-dev/preference/preference/src/main/java/androidx/preference/SeekBarPreference.java
and
https://android.googlesource.com/platform/frameworks/support/+/refs/heads/androidx-master-dev/preference/preference/res/layout/preference_widget_seekbar.xml

Related

Custom design SeekBar in android

I have done the seekbar but I need to do the customization like the below image.
I used the code like this
<SeekBar
android:id="#+id/seekbarPoints"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="-16dp"
android:layout_marginTop="#dimen/small"
android:max="0"
android:progress="0"
android:progressDrawable="#drawable/shape_seekbar_points_style"
android:thumb="#null" />
if (TextUtils.isDigitsOnly(maxPoints)) {
int maxP = Integer.parseInt(maxPoints);
mBinding.seekbarPoints.setMax(maxP);
if (!TextUtils.isEmpty(points)) {
int p = (int) Double.parseDouble(points);
mBinding.seekbarPoints.setProgress(p);
}
}
mBinding.seekbarPoints.setProgressDrawable(ContextCompat.getDrawable(getContext(), R.drawable.shape_seekbar_points_style));
In this image there should be a current points showing textView like the image below
Please suggest some solution for this
Thanks in advance.
you can use following library to achieve your goal
take a look below libray
Library 1
Library 2
Library 3
Library 4

Optimizing Android app for blind people [duplicate]

I am developing an accessible android application where people would be using Explore by Touch and TalkBack accessibility services to use my application.
This is my Android XML code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/LinearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/forename"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dip"
android:layout_marginLeft="15dip"
android:textSize="20sp"
android:text="#string/forenameText"
android:contentDescription="#null"/>
<EditText
android:id="#+id/EditTextForename"
android:layout_width="285dp"
android:layout_height="65dp"
android:layout_marginTop="10dip"
android:layout_marginLeft="15dip"
android:hint="#string/forenameHint"
android:inputType="textPersonName"
android:lines="1"
android:singleLine="true"
android:textSize="20sp" >
</EditText>
</LinearLayout>
strings.xml
<string name="forenameText">Forename</string>
<string name="forenameHint">Enter your forename here</string>
TextView displays the title "Forename" and EditText allows me to enter some details in the form field. The problem I have is that when I
drag my finger across the screen by using Explore by Touch, TalkBack picks up the title of the TextView and announces it aloud as "Forename". I want the TextView to only display text and not provide any audible feedback.
I have set contentDescription to #null as you can see from the code above, but TalkBack still announces "Forename" when my finger is located over the
TextView.
I have also tried setting contentDescription in my Java class:
TextView forename=(TextView)findViewById(R.id.forename);
forename.setContentDescription("");
However, I still get the same problem. Is there any other way to set contentDescription to null/empty and prevent TalkBack from announcing it aloud?
Java code:
public class MainActivity extends Activity{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View forename = findViewById(R.id.forename);
forename.setAccessibilityDelegate(new AccessibilityDelegate() {
public boolean performAccessibilityAction (View host, int action, Bundle args){
return true;
}
});
}
}
Since API 16, Android introduced the following:
android:importantForAccessibility="no"
or
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO)
Which allows developers to disable talkback all together for certain views.
http://developer.android.com/reference/android/view/View.html
For better backwards compatibility:
ViewCompat.setImportantForAccessibility(
decorativeTextView,
ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO);
I was trying to do the same today, and was able to set an 'empty' contentDescription on a TextView like so (using a non-breaking whitespace):
decorativeTextView.setContentDescription("\u00A0");
now TalkBack doesn't say anything for that TextView.
but I agree with Nick about leaving the label as readable in your case, because hint is only read for empty EditTexts.
Why do you not want the TextView to speak "forename"? It is being used as a label for the EditText. Once the user has entered some text the hint "enter your forename here" would no longer be spoken - as far as I know - so the TextView given the user some context for the EditText.
Similarly the announcement of "editbox" gives the user the role of the EditText control. While "form field" might be better it would not be the same behavior as in other apps and in the OS.
I had a similar problem. I eventually solved it by using the setAccessibilityDelegate method and overriding View.AccessibilityDelegate's performAccessibilityAction method.
try this:
View forename = findViewById(R.id.forename);
forename.setAccessibilityDelegate(new AccessibilityDelegate() {
public boolean performAccessibilityAction (View host, int action, Bundle args){
return true;
}
});
I had the same problem, and the only thing that worked for me was android:contentDescription=" " (white space).

osmdroid workaround for the classic markers overlapping

I am developing an Android offline mapping application using osmdroid and osm bonus pack and loading the tiles and data from external storage. Right now, as the data grows, markers are starting to get cramped together, I even have the situation of two places on the same building. I know this kind of issue has been asked a lot before, mine is about a simple temporal workaround I'm thinking of implementing. How about if two places are near enough(right in top of each other!) the standard info window pops up as a ListView with each row designed like the standard bubble(image, title, moreInfoButton).
My question is: some thoughts or advices on how to create the new bonuspack_bubble.xml layout file.
I don't know if this will help you.
I needed to create a CustomInfoBubble for my project. What I did was, to extend the InfoWindow default class, and pass to it my custom bubble layout. Something like this:
http://mobiledevstories.wordpress.com/2014/03/01/osmdroid-bonus-pack-markers-with-clickable-infowindows/
My Java class MapCustomInfoBubble looks like this:
public class MapCustomInfoBubble extends InfoWindow {
public MapCustomInfoBubble(MapView mapView) {
super(R.layout.map_infobubble_black, mapView);//my custom layout and my mapView
}
#Override
public void onClose() {
//by default, do nothing
}
#Override
public void onOpen(Object item) {
Marker marker = (Marker)item; //the marker on which you click to open the bubble
String title = marker.getTitle();
if (title == null)
title = "";
Button moreInfo = (Button)mView.findViewById(R.id.bubble_moreinfo);//the button that I have in my XML;
moreInfo.setText(title);
moreInfo.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
gotoMoreInfoWindow();//custom method; starts another activity
}
});
}
}
In my XML file, I have:
<?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"
android:background="#drawable/map_infobubble_black" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView android:id="#+id/bubble_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:maxEms="17"
android:layout_gravity="left"
android:layout_weight="1"
android:text="Title" />
<Button android:id="#+id/bubble_moreinfo"
android:background="#drawable/map_btn_moreinfo"
android:visibility="visible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_weight="0" />
</LinearLayout>
</LinearLayout>
Somewhere else in my code, I then use:
Marker wp = new Marker(mapView);
wp.setPosition(new GeoPoint(mylocation.getMyLocation()));
wp.setTitle(editTextName.getText().toString());
wp.setInfoWindow(new MapCustomInfoBubble(mapView));
mapView.getOverlays().add(wp);
mapView.invalidate();
In my code, I set the text on the button with the Marker's title.
The Marker is the item on which I click. If you want to put info about more markers in the same InfoWindow (inside a ListView), I think you would need to know in advance what the info will be.
I believe that, You can put whatever code you want inside onOpen(), however, I am not so sure if it's a good practice. You could try creating a custom Constructor and put your logic there. It should work.
You need to pass the Resource Id (layout) and mapView to the super constructor, so it returns a valid mView object.

Android - prevent TalkBack from announcing TextView title aloud

I am developing an accessible android application where people would be using Explore by Touch and TalkBack accessibility services to use my application.
This is my Android XML code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/LinearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/forename"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dip"
android:layout_marginLeft="15dip"
android:textSize="20sp"
android:text="#string/forenameText"
android:contentDescription="#null"/>
<EditText
android:id="#+id/EditTextForename"
android:layout_width="285dp"
android:layout_height="65dp"
android:layout_marginTop="10dip"
android:layout_marginLeft="15dip"
android:hint="#string/forenameHint"
android:inputType="textPersonName"
android:lines="1"
android:singleLine="true"
android:textSize="20sp" >
</EditText>
</LinearLayout>
strings.xml
<string name="forenameText">Forename</string>
<string name="forenameHint">Enter your forename here</string>
TextView displays the title "Forename" and EditText allows me to enter some details in the form field. The problem I have is that when I
drag my finger across the screen by using Explore by Touch, TalkBack picks up the title of the TextView and announces it aloud as "Forename". I want the TextView to only display text and not provide any audible feedback.
I have set contentDescription to #null as you can see from the code above, but TalkBack still announces "Forename" when my finger is located over the
TextView.
I have also tried setting contentDescription in my Java class:
TextView forename=(TextView)findViewById(R.id.forename);
forename.setContentDescription("");
However, I still get the same problem. Is there any other way to set contentDescription to null/empty and prevent TalkBack from announcing it aloud?
Java code:
public class MainActivity extends Activity{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View forename = findViewById(R.id.forename);
forename.setAccessibilityDelegate(new AccessibilityDelegate() {
public boolean performAccessibilityAction (View host, int action, Bundle args){
return true;
}
});
}
}
Since API 16, Android introduced the following:
android:importantForAccessibility="no"
or
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO)
Which allows developers to disable talkback all together for certain views.
http://developer.android.com/reference/android/view/View.html
For better backwards compatibility:
ViewCompat.setImportantForAccessibility(
decorativeTextView,
ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO);
I was trying to do the same today, and was able to set an 'empty' contentDescription on a TextView like so (using a non-breaking whitespace):
decorativeTextView.setContentDescription("\u00A0");
now TalkBack doesn't say anything for that TextView.
but I agree with Nick about leaving the label as readable in your case, because hint is only read for empty EditTexts.
Why do you not want the TextView to speak "forename"? It is being used as a label for the EditText. Once the user has entered some text the hint "enter your forename here" would no longer be spoken - as far as I know - so the TextView given the user some context for the EditText.
Similarly the announcement of "editbox" gives the user the role of the EditText control. While "form field" might be better it would not be the same behavior as in other apps and in the OS.
I had a similar problem. I eventually solved it by using the setAccessibilityDelegate method and overriding View.AccessibilityDelegate's performAccessibilityAction method.
try this:
View forename = findViewById(R.id.forename);
forename.setAccessibilityDelegate(new AccessibilityDelegate() {
public boolean performAccessibilityAction (View host, int action, Bundle args){
return true;
}
});
I had the same problem, and the only thing that worked for me was android:contentDescription=" " (white space).

Is there a view for inputing integers in Android?

I'm looking for something like the individual parts of the date picker dialog. A view that allows you to input integers (and only integers) that you can limit (between 1 and 10 for example), where you can use the keyboard or the arrows in the view itself. Does it exists?
It is for a dialog. A ready-made dialog to request an integer would also help.
The NumberPicker widget is probably what you want. Unfortunately it's located in com.android.internal.Widget.NumberPicker which we cannot get to through normal means.
There are two ways to use it:
Copy the code from android source
Use reflection to access the widget
Here's the xml for using it in a layout:
<com.android.internal.widget.NumberPicker
android:id="#+id/picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
Here's the reflection to set the NumberPicker settings (I have not tested this):
Object o = findViewById(R.id.picker);
Class c = o.getClass();
try
{
Method m = c.getMethod("setRange", int.class, int.class);
m.invoke(o, 0, 9);
}
catch (Exception e)
{
Log.e("", e.getMessage());
}
Since it's an internal widget and not in the SDK, future compatibility could be broken if you use reflection. It would be safest to roll your own from the source.
The original source for this information is shared in this Google Group.
The NumberPicker internal widget has been pulled from the Android source code and packaged for your use and you can find it here. Works great!
EDIT: Original link is down, you can find a copy of the widget here
As has been mentioned elsewhere, NumberPicker is now available in the Android SDK as of API 11 (Android 3.0):
http://developer.android.com/reference/android/widget/NumberPicker.html
For Android < 3.0, you can use the code here:
https://github.com/novak/numpicker-demo
https://github.com/mrn/numberpicker
You can with EditText use android:inputType="number"
<EditText android:layout_height="wrap_content" android:id="#+id/editText1" android:inputType="number" android:layout_width="wrap_content"></EditText>
You can simply use an EditText and define inputType as number. E.g:
<EditText
android:id="#+id/etNumberInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:inputType="number" />
To limit the maximum value to, say 10, you can do it programmatically as:
final EditText et = findViewById(R.id.etNumberInput);
et.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {}
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {}
public void onTextChanged(CharSequence s, int start,
int before, int count) {
if (Integer.parseInt(et.getText().toString()) > 10) {
et.setError("***Your error here***");
// your logic here; to limit the user from inputting
// a value greater than specified limit
}
}
});
This should meet your goal.

Categories

Resources