I am using this TimePickerPreference implementation: http://www.ebessette.com/d/TimePickerPreference
It works nice. But I do not know how to set a default value for it. So if the preference is called the first time, it should show the current time.
I also would like to extend it, to show the chosen time in the title.
In my preference.xml:
<com.example.preference.TimePickerPreference
android:key="quit_time"
android:dialogTitle="Quit"
android:title="Quit"/>
Maybe this code helps you TimePickerPreference.java
Firstly, I apologize for my English, I'm pulling translators . I know the thread is old, but I searched for information on this problem today and nadia had put no solution . What if it happens to anyone else here I leave . This component out there also has the bug that if you cancel the insertion of the time this is always stored . Also comment on your solution.
Let's start with the main thing, is not exactly why he never throws the setter of the default value and the quickest solution would be to manually control element builders. I personally have decided to create a new attribute called "timeByDefault" that is responsible for conducting the functionality of "defaultValue".
/**
* #param context
* #param attrs
*/
public TimePickerPreference(Context context, AttributeSet attrs) {
super(context, attrs);
handleCustomAttributes(context, attrs);
initialize();
}
/**
* #param context
* #param attrs
* #param defStyle
*/
public TimePickerPreference(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
handleCustomAttributes(context, attrs);
initialize();
}
private void handleCustomAttributes(Context context, AttributeSet attrs){
TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.TimePickerPreference);
CharSequence timeByDefaultCS = arr.getString(R.styleable.TimePickerPreference_timeByDefault);
if (null != timeByDefaultCS){
setTimeByDefault(timeByDefaultCS.toString());
}
}
public void setTimeByDefault(Object defaultValue) {
setDefaultValue(defaultValue);
}
Now we create the attribute in "attrs.xml" file in the folder "/res/values​/", and add the following resource:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TimePickerPreference">
< attr name="timeByDefault" format="string" />
</declare-styleable>
</resources>
It will be very important for the new attribute can be accessed from xml will declare xmlns:custom="http://schemas.android.com/apk/res-auto" at the beginning of our xml file in the manner indicated below.
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
>
<PreferenceCategory android:title="Notifications">
<com.mypackage.TimePickerPreference
android:key="KEY_TO_SAVE_THE_TIME_IN_PREFERENCE"
android:title="My custom title"
android:summary="My detail"
android:dialogTitle="My dialog title"
custom:timeByDefault="07:30"
/>
</PreferenceCategory>
</PreferenceScreen>
Now I will explain the issue of canceling the date change:
Opening the dialog box allows us to accept or cancel the new time. This component accepts always time whatever you do. So I created a variable to temporarily store intermediate private time really introduced until accept that value.
private String tmpPersistString = "";
Replace the following function to leave as follows:
#Override
public void onTimeChanged(TimePicker view, int hour, int minute) {
tmpPersistString = hour + ":" + minute;
}
Similarly we control when we pressed one of two buttons, that when we are pressing to accept it then that we store the value of the new time:
#Override
public void onClick(DialogInterface dialog, int which) {
super.getDialog().getCurrentFocus().clearFocus();
super.onClick(dialog, which);
if (which != -2){
persistString(tmpPersistString);
tmpPersistString = "";
}
}
And although it is not entirely necessary to initialize the temporary variable ground when the dialog if the ESC key is pressed to close if you have physical keyboard, or the return button or clicks outside the window.
#Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
tmpPersistString = "";
}
I can only hope that you have understood enough to make this component a good choice at the time to develop and it will be of use to more people. A greeting!
Related
I am trying to customize the Google Cast SDK's Cast Dialog (shown when you tap the cast button and shows the list of available devices), but i haven't found a way to do it.
Currently, it just shows an AlertDialog with a list of the available devices to connect.
What i want to do instead, is open an Activity that will show the list of devices with my own UI implementation.
This is the dialog i am trying to modify:
I've found many customization aspects about this SDK, but nothing related to this dialog.
So i figured out a way to achieve this,
First i created a class that overrides MediaRouteActionProvider (which is the main class that controls that button's functionality)
public class CustomMediaRouteActionProvider extends androidx.mediarouter.app.MediaRouteActionProvider {
public CustomMediaRouteActionProvider(Context context) {
super(context);
}
#Override
public MediaRouteButton onCreateMediaRouteButton() {
return new CastButton(getContext());
}
}
Then you're gonna need to override the button's functionality with your own, in my case i open a new activity.
public class CastButton extends MediaRouteButton {
public CastButton(Context context) {
this(context, null);
}
public CastButton(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.mediaRouteButtonStyle);
}
public CastButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public boolean performClick() {
Intent i = new Intent(getContext(), RemoteDevicesActivity.class);
getContext().startActivity(i);
return true;
}
}
Finally, you need to modify your xml that contains this button (i assume that you already implemented this part)
Change the field app:actionProviderClass with your custom class (in this case CustomMediaRouteActionProvider) and you're done.
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:title="#string/connect_to"
android:id="#+id/cast"
app:actionProviderClass="CustomMediaRouteActionProvider"
app:showAsAction="ifRoom" />
</menu>
Are you have more details of final result of this? I need to do something similar but I don't get it how did you achieve it
to speed up the development of an App I created this editText with a label attached.
This is the class:
public class EditTextWithLabel extends LinearLayout {
#InjectView(R.id.text_edittext_with_label)
protected TextView label;
#InjectView(R.id.edittext_edittext_with_label)
protected EditText editText;
public EditTextWithLabel(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
getAttributes(context, attrs);
}
...
private void init(Context context) {
LayoutInflater.from(context).inflate(R.layout.layout_edittext_with_label, this, true);
ButterKnife.inject(this);
setOrientation(VERTICAL);
}
private void getAttributes(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.EditTextWithLabel, 0, 0);
try {
CharSequence label = a.getText(R.styleable.EditTextWithLabel_label);
if (!TextUtils.isEmpty(label))
setLabel(label);
CharSequence text = a.getText(R.styleable.EditTextWithLabel_android_text);
if (!TextUtils.isEmpty(text))
setText(text);
CharSequence hint = a.getText(R.styleable.EditTextWithLabel_android_hint);
if (!TextUtils.isEmpty(hint))
setHint(hint);
int maxLength = a.getInt(R.styleable.EditTextWithLabel_android_maxLength, -1);
if (maxLength > 0)
setMaxLength(maxLength);
int type = a.getInt(R.styleable.EditTextWithLabel_android_inputType, InputType.TYPE_CLASS_TEXT);
setInputType(type);
} finally {
a.recycle();
}
}
...
}
And this is xml:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="#+id/text_edittext_with_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/edit_text_radius"
android:paddingBottom="5dp"
android:text="#string/username"
android:textColor="#color/text"
android:textSize="#dimen/text_edit_text"
/>
<EditText
android:id="#+id/edittext_edittext_with_label"
style="#style/EditText"
android:inputType="textEmailAddress"/>
</merge>
I found out that if I put more of these in a fragment, when I restore it ALL the editTexts show the text that is wrote in the last one.
I cannot explain this behavior, so I hope that somebody could enlight me.
Thank you
EDIT
Thanks to J. Dow answer I was able to solve the issue, I've added at the end of the init method this code:
label.setId((int) System.currentTimeMillis());
editText.setId((int) System.currentTimeMillis());
This randomized the ids enough to avoid the issue.
What merge is doing is basically a simple include. So your final Layout will include multiple "copies" of your EditText.
From the Android documentation:
Note: In order for the Android system to restore the state of the views in our activity, each view must have a unique ID, supplied by the android:id attribute.
http://developer.android.com/training/basics/activity-lifecycle/recreating.html
Thus, when restoring your merged layout, the Android system will encounter multiple EditTexts with the same id and therefore restore each of them with the same state.
This is really confusing me. I've extended the Button class as follows:
public class MyButton extends Button {
// Default colours/styles
private int myButtonDrawable = R.drawable.button_drawable;
private int myButtonTextColor = R.color.white_text;
// Constructors
public MyButton (Context context) {
super(context);
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyButton (Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
// Override setEnabled to apply custom colors/styles
#Override
public void setEnabled (boolean enabled) {
super.setEnabled(enabled);
if (enabled) {
this.setBackgroundResource(myButtonDrawable);
this.setTextColor(getResources().getColor(myButtonTextColor));
}
}
Thus by using setters I can set values for myButtonDrawable and myButtonTextColor for each MyButton object, and they will be applied when I enable the button using the method setEnabled (i.e. when true).
However, the above code does not work. It crashes out with logcat
Caused by: android.view.InflateException: Binary XML file line #36: Error inflating class
The error is occuring with the line
this.setTextColor(getResources().getColor(myButtonTextColor));
which is really weird because it works fine if I use
this.setTextColor(getResources().getColor(R.color.white_text));
where the resource white_text is defined as
<color name="white_text">#FFFFFFFF</color>
I don't understand why replacing R.color.white_text with the class member myButtonTextColor causes the activity to crash. Anyone got any ideas? Thanks.
Edit: You are extending Button. Button extends TextView, which reads from its XML attributes and calls setEnabled(boolean) in its constructor. However, you have overridden setEnabled() and that method now refers to fields defined in your subclass by initializers.
The initializers for your subclass are not run before the constructor of the superclass. Therefore, at the time setEnabled() is first called by the superclass constructor, myButtonTextColor has the default value and resolving it with Resources.getColor() will throw an error.
If you persist in doing this in code, you may move your if statement to the constructor of your subclass:
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
if (isEnabled()) {
setBackgroundResource(myButtonDrawable);
//FYI, there is a setTextColor method that accepts a color ID.
setTextColor(myButtonTextColor);
}
}
since at the time the constructor of your subclass is called, your initializers are guaranteed to have run, and the superclass constructor will have already resolved the attributes from XML.
Here is an excellent explanation if you'd like to dive more deeply into exactly how Java works in this regard.
There is a better approach for what you want to do. Use a standard Android Button and in your XML (or in code), set a selector as the background and color of your button. You can define an appearance for your button's enabled state -- and many others, including pressed, focused, etc. Android will handle changing the appearance for you.
In your activity (or you can do this in XML):
Button button = new Button();
button.setTextColor(R.drawable.button_text_color);
button.setBackgroundResource(R.drawable.button_background);
drawable/button_text_color.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:color="#color/white_text" />
<item android:color="#color/grey_text" />
</selector>
drawable/button_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:background="#drawable/button_drawable"/>
<item android:background="#drawable/button_disabled_drawable"/>
</selector>
I feel like I must be missing something, but I just don't see what it is... I have a PreferenceActivity with a bunch of various preferences (some are lists, some are just text fields) and it all works fine, but unless I explicitly write each item's value to the summary (which is obviously not intended for this purpose) I don't see how (or where) the items display what they are currently set to. When I click on them the various views show up with the correct settings, but that's clearly not the intention.
Do I have to create my own custom List item of some sort that has a field that displays the currently populated value of each element?
Unfortunately the default PreferencesActivity doesn't display the values: what you're doing is really the way to go if you care to have all the preferences displayed at a glance.
If you still want to go down the programming direction then look at this thread: How do I display the current value of an Android Preference in the Preference summary?
Has everything there.
Create another preference field: summary.
Update it whenever a preference field is updated, or when displaying the preferences screen.
The user will be able to "update" the summary value, but whenever he/she enters preferences, the correct value will be displayed.
For ListPreferences, this is built-in and you can use
android:summary="Actual value: %s"
For EditTextPreferences, you can easily create your own class:
package your.package.preference;
import android.content.Context;
import android.util.AttributeSet;
public class EditTextPreference extends android.preference.EditTextPreference{
public EditTextPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public EditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EditTextPreference(Context context) {
super(context);
}
#Override
public CharSequence getSummary() {
String summary = super.getSummary().toString();
return String.format(summary, getText());
}
}
And use this in your xml:
<your.package.EditTextPreference
android:key="pref_alpha"
android:summary="Actual value: %s"
android:title="Title"
android:defaultValue="default"
/>
I have installed my app in a real phone, and even though in the emulator all the texts of the
preferences summaries seem to be in the same color, in the real phone the color is different (some kind of blue... but I guess it depends on the phone's model).
How can I set this color to my custom preference component?
(I have implemented my own seek bar, and its summary text color is different from all the other components text color...).
Thanks!
Preference pUpdate = findPreference("sys_setting_update");
pUpdate.setSummary(Html.fromHtml("<font color=\"#B0C4DE\">This is content</font>"));
use Html.fromHtml("<font color=\"#B0C4DE\">This is content</font>") to setSummary
I found these: android:textAppearance="?android:attr/textAppearanceLarge"
and android:textAppearance="?android:attr/textAppearanceSmall"
seem to do the trick.
I have figured out a way to retrieve the default color used by the Android device your application is running in. It is a bit tricky and requieres that you retrieve the color being shown from another Preference Summary View of your activity and store it in runtime.
Then you can use the same color code in other Views of other preferences, assuring that you will allways get the same color code Android assigned to the standard preferences. Here is how I did it:
My preferences activity has a normal CheckBoxPreference that I use to activate or deactivate a service. I have extended CheckBoxPreference as follows, so my extension retrieves in rutime the default color Android finally gave to the summary of that CheckBoxPreference:
public class MyCheckBoxPreference extends android.preference.CheckBoxPreference {
private static int sSummaryColor = Color.WHITE;
private static boolean sInitialized = false;
public MyCheckBoxPreference(Context context) {
super(context);
}
public MyCheckBoxPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyCheckBoxPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void onBindView(View view) {
super.onBindView(view);
if (!sInitialized) {
sSummaryColor = getSummaryColor(view);
sInitialized = true;
}
}
private int getSummaryColor(View view) {
int color = Color.WHITE;
// Gets the color android gave to the summary by default
TextView summaryView = (TextView) view.findViewById(android.R.id.summary);
if (summaryView != null) {
ColorStateList list = summaryView.getTextColors();
if (list != null) {
color = list.getDefaultColor();
}
}
return color;
}
public static int getSummaryColor() {
return sSummaryColor;
}
}
In my preferences.xml I instantiate that preference as MyCheckBoxPreference instead of just CheckBoxPreference:
<org.yourpackage.MyCheckBoxPreference
android:title="#string/preference_title_activate"
android:defaultValue="false"
android:summary="#string/preference_summary_activate_off"
android:summaryOff="#string/preference_summary_activate_off"
android:key="preference_activate">
</org.yourpackage.MyCheckBoxPreference>
The MyCheckBoxPreference has to be instantiated once before retrieving the summary color with MyCheckBoxPreference.getSummaryColor().
Now you can set the color of other customized preferences from onBindView(View):
public class MyCustmizedPreference extends Preference {
public MyCustmizedPreference (Context context) {
super(context);
setLayoutResource(R.layout.my_customized_preference);
}
#Override
public void onBindView(View view) {
super.onBindView(view);
TextView summaryView = (TextView) view.findViewById(android.R.id.summary);
if (summaryView != null) {
summaryView.setTextColor(MyCheckBoxPreference.getSummaryColor());
}
}
}
It actually works under Samsung Galaxy S. I have also tested that it doesn't break anything under the emulator.
The Samsung Galaxy S phones have their own Preference layout with the text color specified for the Summary line. Even though a TextAppearance.Small is specified the textColor attribute of the layout is overriding the text appearance.
I don't think this is possible. I am able to change the background color and the title text color, but not the summary color.
Background:
getListView().setBackgroundColor(Color.TRANSPARENT);
Title text:
Preference yourpreference = findPreference("yourpreference");
TextView tv = (TextView)yourpreference.getView(null, getListView());
tv.setTextColor(...);
Sorry I couldn't help more...
I had the same problem and I've been experimenting with my custom seekbar-preference's style. Finally these lines in onCreateView method of seekBarPreference.java show preference's summary with default text color:
TextView summaryText = new TextView(getContext());
summaryText.setText(getSummary());
summaryText.setTextAppearance(getContext(), android.R.style.TextAppearance_Small);
I use it on preference_screen.xml:
<com.asdasf.SeekBarPreferencias
android:key="#string/pref_seekBar_distance_key"
android:id="#+id/mySeekBarPreference"
android:title="#string/pref_seekBar_distance_title"
android:summary="#string/pref_seekBar_distance_summary"
android:max="50"
android:defaultValue="12"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
I hope it will be useful...(and that I have written well my first answer)
Regard!