How to remove end padding of checkable menu item? - android

I have an overflow menu with a checkable menu item. I would like to align the CheckBox all the way to the end, but I don't know how this can be done.
My menu is defined like so:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:icon="#drawable/ic_baseline_more_vert_24"
android:title=""
app:showAsAction="always">
<menu>
<item
android:id="#+id/desktop_site"
android:checkable="true"
android:checked="false"
android:icon="#drawable/ic_baseline_desktop_windows_24"
android:title="Desktop site"
app:showAsAction="never" />
</menu>
</item>
</menu>

You can create a custom style to the CheckBox and adjust the end padding with a negative value:
<style name="checkbox_style" parent="android:style/Widget.Holo.Light.CompoundButton.CheckBox">
<item name="android:paddingRight">-7dp</item>
</style>
And apply it to your app's theme:
<item name="checkboxStyle">#style/checkbox_style</item>
Note: By default there should be some margin surrounds a menu item; so you can't send the checkBox to the far end, as its right edge will cut:
When using -8dp:
So, you need to be careful in handling this.
UPDATE
but it affects all the CheckBoxes in my app
This requires to reverse this padding in all of CheckBoxes in your layouts; and there are options for this:
First option: add android:paddingRight="7dp" / android:paddingEnd="7dp" to all the CheckBoxes.
Second option: Create a custom CheckBox class and add this padding to its constructors; and use this customized CheckBox instead of the default CheckBox:
public class MyCheckBox extends AppCompatCheckBox {
public MyCheckBox(Context context) {
super(context);
init();
}
public MyCheckBox(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
int px = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
7f, // dp value
getResources().getDisplayMetrics()
);
setPadding(0, 0, px, 0);
}
public MyCheckBox(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
}
And to use it:
<!-- Add the full path of the customized CheckBox -->
<com.example.android......MyCheckBox
android:id="#+id/checkbox2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
Hint: If you target API-17+, then use android:paddingEnd instead android:paddingRight

You can use a custom PopupWindow. This allows you to completely customize it.
First create a XML file of your Popup. Using wrap_content at the main layout is very important to shrink the Popup to its size.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#000000"
android:padding="5dp"
android:gravity="center_vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_baseline_desktop_mac_24"
app:tint="#FFFFFF"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Desktop site"
android:textColor="#FFFFFF"
android:layout_marginLeft="10dp"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:buttonTint="#FFFFFF"
android:minWidth="0dp"
android:minHeight="0dp"
android:layout_marginLeft="30dp"/>
</LinearLayout>
</LinearLayout>
Then show the dialog by calling this function. (I copied this code from one of my projects, but I can remember I got it from SO).
private void showPopup(Context context, Point p) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = layoutInflater.inflate(R.layout.your_popup_xml, null);
PopupWindow changeStatusPopUp = new PopupWindow(context);
changeStatusPopUp.setContentView(layout);
changeStatusPopUp.setWidth(LinearLayout.LayoutParams.WRAP_CONTENT);
changeStatusPopUp.setHeight(LinearLayout.LayoutParams.WRAP_CONTENT);
changeStatusPopUp.setAnimationStyle(android.R.style.Animation_Dialog);
int OFFSET_X = -300; //Adjust position of the Popup
int OFFSET_Y = 50; //Adjust position of the Popup
changeStatusPopUp.setOutsideTouchable(true);
changeStatusPopUp.setFocusable(true);
changeStatusPopUp.setBackgroundDrawable(new BitmapDrawable());
changeStatusPopUp.showAtLocation(layout, Gravity.NO_GRAVITY, p.x + OFFSET_X, p.y + OFFSET_Y);
}
If you want to catch Click Events, you just need to set an id to the LinearLayout and use it with the view in Java (LinearLayout ll = view.findViewById(R.id.yourId);).
Call the void by:
int[] location = new int[2];
view.getLocationOnScreen(location);
Point point = new Point();
point.x = location[0];
point.y = location[1];
showStatusPopup(context, point);

When using MaterialComponents some of the padding is from the checkbox itself. This can be removed by setting android:minWidth to 0. The remaining padding is symmetrical and looks good.
Like the accepted solution, create a style:
<style name="checkbox_style" parent="#style/Widget.MaterialComponents.CompoundButton.CheckBox">
<item name="minWidth">0dp</item>
</style>
And apply it to your app's theme:
<item name="checkboxStyle">#style/checkbox_style</item>

Related

How can I change style of views dynamically? [duplicate]

Here's XML:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
style="#style/LightStyle"
android:layout_width="fill_parent"
android:layout_height="55dip"
android:clickable="true"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" />
</RelativeLayout>
How to set style attribute programmatically?
Technically you can apply styles programmatically, with custom views anyway:
private MyRelativeLayout extends RelativeLayout {
public MyRelativeLayout(Context context) {
super(context, null, R.style.LightStyle);
}
}
The one argument constructor is the one used when you instantiate views programmatically.
So chain this constructor to the super that takes a style parameter.
RelativeLayout someLayout = new MyRelativeLayout(new ContextThemeWrapper(this,R.style.RadioButton));
Or as #Dori pointed out simply:
RelativeLayout someLayout = new RelativeLayout(new ContextThemeWrapper(activity,R.style.LightStyle));
Now in Kotlin:
class MyRelativeLayout #JvmOverloads constructor(
context: Context,
attributeSet: AttributeSet? = null,
defStyleAttr: Int = R.style.LightStyle,
) : RelativeLayout(context, attributeSet, defStyleAttr)
or
val rl = RelativeLayout(ContextThemeWrapper(activity, R.style.LightStyle))
What worked for me:
Button b = new Button(new ContextThemeWrapper(this, R.style.ButtonText), null, 0);
Use a ContextThemeWrapper
AND
Use the 3-arguments constructor (won't work without this)
Update: At the time of answering this question (mid 2012, API level 14-15), setting the view programmatically was not an option (even though there were some non-trivial workarounds) whereas this has been made possible after the more recent API releases. See #Blundell's answer for details.
OLD Answer:
You cannot set a view's style programmatically yet, but you may find this thread useful.
For a new Button/TextView:
Button mMyButton = new Button(new ContextThemeWrapper(this, R.style.button_disabled), null, 0);
For an existing instance:
mMyButton.setTextAppearance(this, R.style.button_enabled);
For Image or layouts:
Image mMyImage = new ImageView(new ContextThemeWrapper(context, R.style.article_image), null, 0);
This is quite old question but solution that worked for me now is to use 4th parameter of constructor defStyleRes - if available.. on view... to set style
Following works for my purposes (kotlin):
val textView = TextView(context, null, 0, R.style.Headline1)
If you'd like to continue using XML (which the accepted answer doesn't let you do) and set the style after the view has been created you may be able to use the Paris library which supports a subset of all available attributes.
Since you're inflating your view from XML you'd need to specify an id in the layout:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/my_styleable_relative_layout"
style="#style/LightStyle"
...
Then when you need to change the style programmatically, after the layout has been inflated:
// Any way to get the view instance will do
RelativeLayout myView = findViewById(R.id.my_styleable_relative_layout);
// This will apply all the supported attribute values of the style
Paris.style(myView).apply(R.style.LightStyle);
For more: the list of supported view types and attributes (includes background, padding, margin, etc. and can easily be extended) and installation instructions with additional documentation.
Disclaimer: I'm the original author of said library.
You can apply a style to your activity by doing:
super.setTheme( R.style.MyAppTheme );
or Android default:
super.setTheme( android.R.style.Theme );
in your activity, before setContentView().
Non of the provided answers are correct.
You CAN set style programatically.
Short answer is take a look at http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/content/Context.java#435
Long answer.
Here's my snippet to set custom defined style programatically to your view:
1) Create a style in your styles.xml file
<style name="MyStyle">
<item name="customTextColor">#39445B</item>
<item name="customDividerColor">#8D5AA8</item>
</style>
Do not forget to define your custom attributes in attrs.xml file
My attrsl.xml file:
<declare-styleable name="CustomWidget">
<attr name="customTextColor" format="color" />
<attr name="customDividerColor" format="color" />
</declare-styleable>
Notice you can use any name for your styleable (my CustomWidget)
Now lets set the style to the widget Programatically
Here's My simple widget:
public class StyleableWidget extends LinearLayout {
private final StyleLoader styleLoader = new StyleLoader();
private TextView textView;
private View divider;
public StyleableWidget(Context context) {
super(context);
init();
}
private void init() {
inflate(getContext(), R.layout.widget_styleable, this);
textView = (TextView) findViewById(R.id.text_view);
divider = findViewById(R.id.divider);
setOrientation(VERTICAL);
}
protected void apply(StyleLoader.StyleAttrs styleAttrs) {
textView.setTextColor(styleAttrs.textColor);
divider.setBackgroundColor(styleAttrs.dividerColor);
}
public void setStyle(#StyleRes int style) {
apply(styleLoader.load(getContext(), style));
}
}
layout:
<TextView
android:id="#+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22sp"
android:layout_gravity="center"
android:text="#string/styleble_title" />
<View
android:id="#+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"/>
</merge>
And finally StyleLoader class implementation
public class StyleLoader {
public StyleLoader() {
}
public static class StyleAttrs {
public int textColor;
public int dividerColor;
}
public StyleAttrs load(Context context, #StyleRes int styleResId) {
final TypedArray styledAttributes = context.obtainStyledAttributes(styleResId, R.styleable.CustomWidget);
return load(styledAttributes);
}
#NonNull
private StyleAttrs load(TypedArray styledAttributes) {
StyleAttrs styleAttrs = new StyleAttrs();
try {
styleAttrs.textColor = styledAttributes.getColor(R.styleable.CustomWidget_customTextColor, 0);
styleAttrs.dividerColor = styledAttributes.getColor(R.styleable.CustomWidget_customDividerColor, 0);
} finally {
styledAttributes.recycle();
}
return styleAttrs;
}
}
You can find fully working example at https://github.com/Defuera/SetStylableProgramatically
This is my simple example, the key is the ContextThemeWrapper wrapper, without it, my style does not work, and using the three parameters constructor of the View.
ContextThemeWrapper themeContext = new ContextThemeWrapper(this, R.style.DefaultLabelStyle);
TextView tv = new TextView(themeContext, null, 0);
tv.setText("blah blah ...");
layout.addView(tv);
the simple way is passing through constructor
RadioButton radioButton = new RadioButton(this,null,R.style.radiobutton_material_quiz);
I don't propose to use ContextThemeWrapper as it do this:
The specified theme will be applied on top of
the base context's theme.
What can make unwanted results in your application. Instead I propose new library "paris" for this from engineers at Airbnb:
https://github.com/airbnb/paris
Define and apply styles to Android views programmatically.
But after some time of using it I found out it's actually quite limited and I stopped using it because it does not support a lot of properties i need out off the box, so one have to check out and decide as always.
int buttonStyle = R.style.your_button_style;
Button button = new Button(new ContextThemeWrapper(context, buttonStyle), null, buttonStyle);
Only this answer works for me. See https://stackoverflow.com/a/24438579/5093308
best simple solution i found, using alertDialog with a custom layout, is :
val mView = LayoutInflater.from(context).inflate(layoutResId, null)
val dialog = AlertDialog.Builder(context, R.style.CustomAlertDialog)
.setView(mView)
.setCancelable(false)
.create()
where style is
<style name="CustomAlertDialog" parent="Theme.AppCompat.Light.Dialog.Alert">
<item name="android:background">#drawable/bg_dialog_white_rounded</item>
</style>
and bg_dialog_white_rounded.xml is
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="16dp" />
<solid android:color="#Color/white" />
</shape>
layoutResId is a resource id of any layout that has to have the theme set to "#style/CustomAlertDialog", for example:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="#dimen/wdd_margin_medium"
android:theme="#style/CustomAlertDialog"
android:layout_marginEnd="#dimen/wdd_margin_medium">
..... etc...
</androidx.constraintlayout.widget.ConstraintLayout>
I used views defined in XML in my composite ViewGroup, inflated them added to Viewgroup. This way I cannot dynamically change style but I can make some style customizations. My composite:
public class CalendarView extends LinearLayout {
private GridView mCalendarGrid;
private LinearLayout mActiveCalendars;
private CalendarAdapter calendarAdapter;
public CalendarView(Context context) {
super(context);
}
public CalendarView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
init();
}
private void init() {
mCalendarGrid = (GridView) findViewById(R.id.calendarContents);
mCalendarGrid.setNumColumns(CalendarAdapter.NUM_COLS);
calendarAdapter = new CalendarAdapter(getContext());
mCalendarGrid.setAdapter(calendarAdapter);
mActiveCalendars = (LinearLayout) findViewById(R.id.calendarFooter);
}
}
and my view in xml where i can assign styles:
<com.mfitbs.android.calendar.CalendarView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/calendar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:orientation="vertical"
>
<GridView
android:id="#+id/calendarContents"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:id="#+id/calendarFooter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
/>
if inside own custom view :
val editText = TextInputEditText(context, attrs, defStyleAttr)
You can create the xml containing the layout with the desired style and then change the background resource of your view, like this.

Android Text should appear both side in the Switch

I using custom switch for support of API 8. I am using THIS Libarary for Custom Switch. But I want to make something Like show in figure.I have tried to change the color ,though changing the color in the style but doesn't effect as i want.
Please help me , Thanks in advance.
Here's a full, working solution, after a fun day implementing this.
Use the following to set the drawable for the track of the switch. The track is the container within which the thumb slides left and right.
mMessengerSwitch.setTrackDrawable(new SwitchTrackTextDrawable(this,
"LEFT", "RIGHT"));
Here's the implementation of the SwitchTrackTextDrawable, which writes the text in the background exactly in the right position (well, I've only tested it for API 23 on a Nexus 5):
/**
* Drawable that generates the two pieces of text in the track of the switch, one of each
* side of the positions of the thumb.
*/
public class SwitchTrackTextDrawable extends Drawable {
private final Context mContext;
private final String mLeftText;
private final String mRightText;
private final Paint mTextPaint;
public SwitchTrackTextDrawable(#NonNull Context context,
#StringRes int leftTextId,
#StringRes int rightTextId) {
mContext = context;
// Left text
mLeftText = context.getString(leftTextId);
mTextPaint = createTextPaint();
// Right text
mRightText = context.getString(rightTextId);
}
private Paint createTextPaint() {
Paint textPaint = new Paint();
//noinspection deprecation
textPaint.setColor(mContext.getResources().getColor(android.R.color.white));
textPaint.setAntiAlias(true);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextAlign(Paint.Align.CENTER);
// Set textSize, typeface, etc, as you wish
return textPaint;
}
#Override
public void draw(Canvas canvas) {
final Rect textBounds = new Rect();
mTextPaint.getTextBounds(mRightText, 0, mRightText.length(), textBounds);
// The baseline for the text: centered, including the height of the text itself
final int heightBaseline = canvas.getClipBounds().height() / 2 + textBounds.height() / 2;
// This is one quarter of the full width, to measure the centers of the texts
final int widthQuarter = canvas.getClipBounds().width() / 4;
canvas.drawText(mLeftText, 0, mLeftText.length(),
widthQuarter, heightBaseline,
mTextPaint);
canvas.drawText(mRightText, 0, mRightText.length(),
widthQuarter * 3, heightBaseline,
mTextPaint);
}
#Override
public void setAlpha(int alpha) {
}
#Override
public void setColorFilter(ColorFilter cf) {
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
Try using
android:textOn="On"
android:textOff="Off"
instead of
android:text="On"
in switches.
You can also go through this if it helps.
After struggling to find the right solution for this, I found this neat little library. I found it easy to use and it met my needs perfectly. It can even be used to display more than 2 values.
UPDATE: In the meanwhile this library has stopped being maintained, so you may want to try the one they recommend.
This is how I made it look eventually with some more styling, like white border which I put around a FrameLayout that wraps it (I needed to make it look exactly like this, you need not use border):
Here's the xml for this:
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="1dp"
android:background="#drawable/white_border">
<belka.us.androidtoggleswitch.widgets.ToggleSwitch
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:activeBgColor="#color/white"
custom:activeTextColor="#color/black"
custom:inactiveBgColor="#color/black"
custom:inactiveTextColor="#color/white"
custom:textToggleLeft="left"
custom:textToggleRight="right"/>
</FrameLayout>
And #drawable/white_border looks like this:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<solid android:color="#android:color/transparent" />
<stroke android:width="2dip"
android:color="#color/white" />
<corners
android:radius="3dp"/>
I created a custom layout that contain a linear layout (will be used as a track of the switch) in this layout I placed two texts to simulate the track "on"/"off" texts, and on top of it, it has a regular switch but without a track, just a thumb with transparent track.
Anyway this is the code:
colors.xml
<color name="switch_selected_text_color">#FFFFFF</color>
<color name="switch_regular_text_color">#A8A8A8</color>
settings_switch_color_selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/switch_selected_text_color" android:state_checked="true" />
<item android:color="#color/switch_regular_text_color" />
</selector>
styles.xml
<style name="SwitchTextAppearance" parent="#android:style/TextAppearance.Holo.Small">
<item name="android:textColor">#color/settings_switch_color_selector</item>
</style>
new_switch.xml - used in the custom view
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/track_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/settings_track"
android:weightSum="1">
<TextView
android:id="#+id/left_text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:textColor="#color/switch_regular_text_color"
android:layout_weight="0.5"
android:gravity="center"
android:text="OFF" />
<TextView
android:id="#+id/right_text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:textColor="#color/switch_regular_text_color"
android:layout_weight="0.5"
android:gravity="center"
android:text="ON" />
</LinearLayout>
<Switch
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:thumb="#drawable/thumb_selector"
android:switchTextAppearance="#style/SwitchTextAppearance"
android:textOn="ON"
android:textOff="OFF"
android:checked="true"
android:showText="true"
android:track="#android:color/transparent"/>
</RelativeLayout>
this is custom view - it`s just for inflating the custom view layout
public class DoubleSidedSwitch extends RelativeLayout {
private TextView _leftTextView;
private TextView _rightTextView;
private Switch _switch;
public DoubleSidedSwitch(Context context) {
super(context);
init(context);
}
public DoubleSidedSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
View view = LayoutInflater.from(context).inflate(R.layout.new_switch, this, true);
initViews(view);
initListeners();
}
private void initListeners() {
}
private void initViews(View view) {
}
}
There is one made by 2 Standard buttons and a LinearLayout. There are bunch of xml files to import but it works perfect on all versions and very easy to use. Check the following Github Page
Custom Switch With 2 Buttons
usage
Copy XML files under res/drawable to your project's res/drawable folder.
Copy LinearLayout from layout.xml to your layout file.
Copy values from values/colors.xml and values/dimens to your own files.
Initilize the switch with following code
SekizbitSwitch mySwitch = new SekizbitSwitch(findViewById(R.id.sekizbit_switch));
mySwitch.setOnChangeListener(new SekizbitSwitch.OnSelectedChangeListener() {
#Override
public void OnSelectedChange(SekizbitSwitch sender) {
if(sender.getCheckedIndex() ==0 )
{
System.out.println("Left Button Selected");
}
else if(sender.getCheckedIndex() ==1 )
{
System.out.println("Right Button Selected");
}
}
});

Changing the highlighting colors (button colors) of a "DialogPreference"

I implemented a DialogPreference exactly the way it is explained in http://www.lukehorvat.com/blog/android-seekbardialogpreference
Additionally I was able to change the text- and divider color of the DialogPreference, but I couldn't change the highlighting color of the buttons when they are pressed. Does anybody know how to do this?
Update:
I use the following layout for the DialogPreference:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/text_dialog_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dip"
android:paddingLeft="12dip"
android:paddingRight="12dip"/>
<TextView
android:id="#+id/text_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dip"
android:gravity="center_horizontal"/>
<SeekBar
android:id="#+id/seek_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="6dip"
android:layout_marginTop="6dip"/>
</LinearLayout>
The only style attributes regarding this DialogPreference or the layout I change so far are changed programatically:
int alertTitleId = this.getContext().getResources().getIdentifier("alertTitle", "id", "android");
TextView alertTitle = (TextView) getDialog().getWindow().getDecorView().findViewById(alertTitleId);
alertTitle.setTextColor(color); // change title text color
int titleDividerId = this.getContext().getResources().getIdentifier("titleDivider", "id", "android");
View titleDivider = getDialog().getWindow().getDecorView().findViewById(titleDividerId);
titleDivider.setBackgroundColor(color); // change divider color
All you need to do is subclass DialogPreference, then call Resource.getIdentifier to locate each View you want to theme, much like you're doing, but you don't need to call Window.getDecorView. Here's an example:
Custom DialogPreference
public class CustomDialogPreference extends DialogPreference {
public CustomDialogPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomDialogPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* {#inheritDoc}
*/
#Override
protected void showDialog(Bundle state) {
super.showDialog(state);
final Resources res = getContext().getResources();
final Window window = getDialog().getWindow();
final int green = res.getColor(android.R.color.holo_green_dark);
// Title
final int titleId = res.getIdentifier("alertTitle", "id", "android");
final View title = window.findViewById(titleId);
if (title != null) {
((TextView) title).setTextColor(green);
}
// Title divider
final int titleDividerId = res.getIdentifier("titleDivider", "id", "android");
final View titleDivider = window.findViewById(titleDividerId);
if (titleDivider != null) {
titleDivider.setBackgroundColor(green);
}
// Button views
window.findViewById(res.getIdentifier("button1", "id", "android"))
.setBackgroundDrawable(res.getDrawable(R.drawable.your_selector));
window.findViewById(res.getIdentifier("button2", "id", "android"))
.setBackgroundDrawable(res.getDrawable(R.drawable.your_selector));
window.findViewById(res.getIdentifier("button3", "id", "android"))
.setBackgroundDrawable(res.getDrawable(R.drawable.your_selector));
}
}
XML preferences
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<path_to.CustomDialogPreference
android:dialogMessage="Message"
android:negativeButtonText="Cancel"
android:positiveButtonText="Okay"
android:title="Title" />
</PreferenceScreen>
Custom selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true">
<item android:drawable="#drawable/your_pressed_drawable" android:state_pressed="true"/>
<item android:drawable="#drawable/your_default_drawable"/>
</selector>
Alternate selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true">
<item android:drawable="#color/your_pressed_color" android:state_pressed="true"/>
<item android:drawable="#color/your_default_color/>
</selector>
Screenshot
If you fail to find a solution for styling the built-in buttons to your liking, you could actually add a button row to the bottom of your custom layout, which looks and acts exactly like the built-in one. Then set your button listeners to your custom button bar's buttons, which will result in no built-in button bar.
In this way you can make them look however you want!
I you can try this Answer. Here you don't need write code just need customise AlertDialog theme.
After customisation theme it may be applicable for your complete application.

Put on the right the indicator of an ExpandableListView in Android

I have to move the indicator from the left to the right (because of the plane image). I couldn't succeed also because the expandableviewlist is inside a fragment and not inside a whole activity. Any idea? Thanks!
I don't know a way to do that from XML but i'll tell you a way to do so dynamically in your adapter.
First you have to remove group indicator from your xml
<ExpandableListView [...]
android:groupIndicator="#null" />
Then in your layout of the parent add an imageview in the right position of your layout.
Then in your custom adapter do the following
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
...
if (isExpanded) {
groupHolder.img.setImageResource(R.drawable.group_down);
} else {
groupHolder.img.setImageResource(R.drawable.group_up);
}
...
}
One more solution is:
1) First set groupIndicator in your ExpandableListView to #null:
<ExpandableListView [...]
android:groupIndicator="#null" />
2) Then create group_indicator.xml file with following details:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/down_icon" android:state_selected="false"></item>
<item android:drawable="#drawable/up_icon" android:state_selected="true"></item>
<item android:drawable="#drawable/down_icon"></item>
</selector>
3) Then create group_header.xml layout with following details and inflate this layout in getGroupView() method of ExpandableListAdapter.java:
<?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="wrap_content"
android:padding="10dp">
<TextView
android:id="#+id/tvHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:textColor="#color/white"
android:layout_centerVertical="true"
android:textSize="16sp"/>
<ImageView
android:id="#+id/ivGroupIndicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/group_indicator"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"/>
</RelativeLayout>
3) In getGroupView() method of your ExpandableListAdapter.java class, just set the following:
ivGroupIndicator.setSelected(isExpanded);
With this approach, your down_icon and up_icon will work properly.
Hope this helps.
put this into your xml view:
<ExpandableListView
...
android:layoutDirection="rtl" />
than you can set the gravity of your text title in your layout item according your preference.
your text view parent list item:
<TextView
...
android:gravity="center"/>
eg. result:
another solution to put the indicator on the right programmatically:
expandableListView = (ExpandableListView) findViewById(R.id.expandableListView);
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
Resources r = getResources();
int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
50, r.getDisplayMetrics());
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
expandableListView.setIndicatorBounds(width - px, width);
} else {
expandableListView.setIndicatorBoundsRelative(width - px, width);
}
where expandableListView is your ExpandableListview
In your groupcustom.xml file you can use Relativelayout and put that image to
android:alignParentRight = "true";

Android: set view style programmatically

Here's XML:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
style="#style/LightStyle"
android:layout_width="fill_parent"
android:layout_height="55dip"
android:clickable="true"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" />
</RelativeLayout>
How to set style attribute programmatically?
Technically you can apply styles programmatically, with custom views anyway:
private MyRelativeLayout extends RelativeLayout {
public MyRelativeLayout(Context context) {
super(context, null, R.style.LightStyle);
}
}
The one argument constructor is the one used when you instantiate views programmatically.
So chain this constructor to the super that takes a style parameter.
RelativeLayout someLayout = new MyRelativeLayout(new ContextThemeWrapper(this,R.style.RadioButton));
Or as #Dori pointed out simply:
RelativeLayout someLayout = new RelativeLayout(new ContextThemeWrapper(activity,R.style.LightStyle));
Now in Kotlin:
class MyRelativeLayout #JvmOverloads constructor(
context: Context,
attributeSet: AttributeSet? = null,
defStyleAttr: Int = R.style.LightStyle,
) : RelativeLayout(context, attributeSet, defStyleAttr)
or
val rl = RelativeLayout(ContextThemeWrapper(activity, R.style.LightStyle))
What worked for me:
Button b = new Button(new ContextThemeWrapper(this, R.style.ButtonText), null, 0);
Use a ContextThemeWrapper
AND
Use the 3-arguments constructor (won't work without this)
Update: At the time of answering this question (mid 2012, API level 14-15), setting the view programmatically was not an option (even though there were some non-trivial workarounds) whereas this has been made possible after the more recent API releases. See #Blundell's answer for details.
OLD Answer:
You cannot set a view's style programmatically yet, but you may find this thread useful.
For a new Button/TextView:
Button mMyButton = new Button(new ContextThemeWrapper(this, R.style.button_disabled), null, 0);
For an existing instance:
mMyButton.setTextAppearance(this, R.style.button_enabled);
For Image or layouts:
Image mMyImage = new ImageView(new ContextThemeWrapper(context, R.style.article_image), null, 0);
This is quite old question but solution that worked for me now is to use 4th parameter of constructor defStyleRes - if available.. on view... to set style
Following works for my purposes (kotlin):
val textView = TextView(context, null, 0, R.style.Headline1)
If you'd like to continue using XML (which the accepted answer doesn't let you do) and set the style after the view has been created you may be able to use the Paris library which supports a subset of all available attributes.
Since you're inflating your view from XML you'd need to specify an id in the layout:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/my_styleable_relative_layout"
style="#style/LightStyle"
...
Then when you need to change the style programmatically, after the layout has been inflated:
// Any way to get the view instance will do
RelativeLayout myView = findViewById(R.id.my_styleable_relative_layout);
// This will apply all the supported attribute values of the style
Paris.style(myView).apply(R.style.LightStyle);
For more: the list of supported view types and attributes (includes background, padding, margin, etc. and can easily be extended) and installation instructions with additional documentation.
Disclaimer: I'm the original author of said library.
You can apply a style to your activity by doing:
super.setTheme( R.style.MyAppTheme );
or Android default:
super.setTheme( android.R.style.Theme );
in your activity, before setContentView().
Non of the provided answers are correct.
You CAN set style programatically.
Short answer is take a look at http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/content/Context.java#435
Long answer.
Here's my snippet to set custom defined style programatically to your view:
1) Create a style in your styles.xml file
<style name="MyStyle">
<item name="customTextColor">#39445B</item>
<item name="customDividerColor">#8D5AA8</item>
</style>
Do not forget to define your custom attributes in attrs.xml file
My attrsl.xml file:
<declare-styleable name="CustomWidget">
<attr name="customTextColor" format="color" />
<attr name="customDividerColor" format="color" />
</declare-styleable>
Notice you can use any name for your styleable (my CustomWidget)
Now lets set the style to the widget Programatically
Here's My simple widget:
public class StyleableWidget extends LinearLayout {
private final StyleLoader styleLoader = new StyleLoader();
private TextView textView;
private View divider;
public StyleableWidget(Context context) {
super(context);
init();
}
private void init() {
inflate(getContext(), R.layout.widget_styleable, this);
textView = (TextView) findViewById(R.id.text_view);
divider = findViewById(R.id.divider);
setOrientation(VERTICAL);
}
protected void apply(StyleLoader.StyleAttrs styleAttrs) {
textView.setTextColor(styleAttrs.textColor);
divider.setBackgroundColor(styleAttrs.dividerColor);
}
public void setStyle(#StyleRes int style) {
apply(styleLoader.load(getContext(), style));
}
}
layout:
<TextView
android:id="#+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22sp"
android:layout_gravity="center"
android:text="#string/styleble_title" />
<View
android:id="#+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"/>
</merge>
And finally StyleLoader class implementation
public class StyleLoader {
public StyleLoader() {
}
public static class StyleAttrs {
public int textColor;
public int dividerColor;
}
public StyleAttrs load(Context context, #StyleRes int styleResId) {
final TypedArray styledAttributes = context.obtainStyledAttributes(styleResId, R.styleable.CustomWidget);
return load(styledAttributes);
}
#NonNull
private StyleAttrs load(TypedArray styledAttributes) {
StyleAttrs styleAttrs = new StyleAttrs();
try {
styleAttrs.textColor = styledAttributes.getColor(R.styleable.CustomWidget_customTextColor, 0);
styleAttrs.dividerColor = styledAttributes.getColor(R.styleable.CustomWidget_customDividerColor, 0);
} finally {
styledAttributes.recycle();
}
return styleAttrs;
}
}
You can find fully working example at https://github.com/Defuera/SetStylableProgramatically
This is my simple example, the key is the ContextThemeWrapper wrapper, without it, my style does not work, and using the three parameters constructor of the View.
ContextThemeWrapper themeContext = new ContextThemeWrapper(this, R.style.DefaultLabelStyle);
TextView tv = new TextView(themeContext, null, 0);
tv.setText("blah blah ...");
layout.addView(tv);
the simple way is passing through constructor
RadioButton radioButton = new RadioButton(this,null,R.style.radiobutton_material_quiz);
I don't propose to use ContextThemeWrapper as it do this:
The specified theme will be applied on top of
the base context's theme.
What can make unwanted results in your application. Instead I propose new library "paris" for this from engineers at Airbnb:
https://github.com/airbnb/paris
Define and apply styles to Android views programmatically.
But after some time of using it I found out it's actually quite limited and I stopped using it because it does not support a lot of properties i need out off the box, so one have to check out and decide as always.
int buttonStyle = R.style.your_button_style;
Button button = new Button(new ContextThemeWrapper(context, buttonStyle), null, buttonStyle);
Only this answer works for me. See https://stackoverflow.com/a/24438579/5093308
best simple solution i found, using alertDialog with a custom layout, is :
val mView = LayoutInflater.from(context).inflate(layoutResId, null)
val dialog = AlertDialog.Builder(context, R.style.CustomAlertDialog)
.setView(mView)
.setCancelable(false)
.create()
where style is
<style name="CustomAlertDialog" parent="Theme.AppCompat.Light.Dialog.Alert">
<item name="android:background">#drawable/bg_dialog_white_rounded</item>
</style>
and bg_dialog_white_rounded.xml is
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="16dp" />
<solid android:color="#Color/white" />
</shape>
layoutResId is a resource id of any layout that has to have the theme set to "#style/CustomAlertDialog", for example:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="#dimen/wdd_margin_medium"
android:theme="#style/CustomAlertDialog"
android:layout_marginEnd="#dimen/wdd_margin_medium">
..... etc...
</androidx.constraintlayout.widget.ConstraintLayout>
I used views defined in XML in my composite ViewGroup, inflated them added to Viewgroup. This way I cannot dynamically change style but I can make some style customizations. My composite:
public class CalendarView extends LinearLayout {
private GridView mCalendarGrid;
private LinearLayout mActiveCalendars;
private CalendarAdapter calendarAdapter;
public CalendarView(Context context) {
super(context);
}
public CalendarView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
init();
}
private void init() {
mCalendarGrid = (GridView) findViewById(R.id.calendarContents);
mCalendarGrid.setNumColumns(CalendarAdapter.NUM_COLS);
calendarAdapter = new CalendarAdapter(getContext());
mCalendarGrid.setAdapter(calendarAdapter);
mActiveCalendars = (LinearLayout) findViewById(R.id.calendarFooter);
}
}
and my view in xml where i can assign styles:
<com.mfitbs.android.calendar.CalendarView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/calendar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:orientation="vertical"
>
<GridView
android:id="#+id/calendarContents"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:id="#+id/calendarFooter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
/>
if inside own custom view :
val editText = TextInputEditText(context, attrs, defStyleAttr)
You can create the xml containing the layout with the desired style and then change the background resource of your view, like this.

Categories

Resources