Modify all buttons text size programmatically? - android

I need to change the text color of all buttons in a view programmatically.
Right now I'm modifying them one by one like this:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = inflater.inflate(R.layout.fragment_screen_dialer, container, false);
Button b = (Button) view.findViewById(R.id.button0);
b.setTextColor(value);
b = (Button) view.findViewById(R.id.button1);
b.setTextColor(value);
But since there are a lot of buttons I want to modify them all at once? How can this be done?

Iterate through all children of your layout, checking if next view is instance of Button or its subclass:
ViewGroup viewgroup = (ViewGroup) findViewById(R.id.your_layout);
int count = viewgroup.getChildCount();
for (int i=0; i < count; i++){
View view = viewgroup.getChildAt(i);
if (view instanceof Button){
(Button)view.setTextColor(value);
}
}
This will work if your buttons lays on the same level. Otherwise you need to build a recurrent function similar to this:
public void setNewColor(View view, int value){
if (view instanceof Button){
((Button) view).setTextColor(value);
}
else if (view instanceof ViewGroup){
ViewGroup viewgroup = (ViewGroup)view;
int count = viewgroup.getChildCount();
for (int i=0; i < count; i++){
View viewNext = viewgroup.getChildAt(i);
setNewColor(viewNext, value);
}
}
}
and apply it to your layout:
setNewColor(findViewById(R.id.your_layout), your_color);

AFAIK, you can't modify the color or other property of layout elements in a view at once. You have to do how you are doing, i.e. set the color one by one.
However, you can create a button style in style.xml and assign the syle to all buttons and whenever you will change style.xml it will effect all the buttons

You may have to iterate over all the views, and change colors of the buttons. Check this page for how to traverse all child view / view groups of your layout, including views (button) that are not direct children of your main layout
Including the two classes provided, you will write easy code like:
ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
List<Button> buttons = Views.find(root, Button.class);
for (Button b: buttons)
b.setTextColor(value);

Related

Set visibility for view to gone for an inflated layout

I am trying to set the visibility of some views as gone after layout inflation but it doesn't work. If I try to access the tag of the view , I can clearly see that I am accessing the right view. This code doesn't result to any errors, so I am trying to understand why it's not working.
I am passing in as parameters the resource ids for the views (hideView) and the layout(layout):
public void hideViews(String title, ArrayList<Integer> hideView, int layout){
final LayoutInflater factory = getLayoutInflater();
final View originalView = factory.inflate(layout, null);
for (int i = 0; i < hideView.size(); i++) {
View view = originalView.findViewById(hideView.get(i));
if (title.equals("Admin") || title.equals("Manager")){
view.setVisibility(View.VISIBLE);
}else{
view.setVisibility(View.GONE);
}
}
}
originalView is not attached to your layout.
Either provide the parent view where you want to inflate this layout
Or add originalView as a child of other attached view after inflating.
Let's assume that this is your parent view
ViewGroup parentView = (ViewGroup)findViewById(R.id.parentView);
Solution 1
Replace this:
final View originalView = factory.inflate(layout, null);
With:
final View originalView = factory.inflate(layout, parentView);
Solution 2
Add this:
parentView.add(originalView)

Get list of all on screen UI elements

It is possible to get a list of all the currently displayed/on-screen android UI elements?
For example, if I have a app that look like this:
I would get a list that would contain:
TextView (Hello World!)
RelativeLayout (Or whatever the parent container is)
Etc if there were more elements
This would be great in the case I don't know the ID's, or even what UI elements will appear on screen, but I still want to hide/show them.
You can achieve this by using the following manager, nice and clean!
Use it anywhere you want and you'll get a list of the view and all its children.
(Needs to be done recursively)
LayoutManager.getViews(getWindow());
public class LayoutManager
{
private static List<View> views;
public static List<View> getViews(Window window) {
return getViews(window.getDecorView().getRootView(), true);
}
public static List<View> getViews(final View view, boolean starting)
{
if (starting) {
views = new ArrayList<>();
}
views.add(view);
/** Search in each ViewGroup children as well */
if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
getViews(viewGroup.getChildAt(i), false);
}
}
return views;
}
}

Equivalent of CSS class selectors for Android views?

Do Android views have something equivalent to CSS class selectors? Something like R.id but usable for multiple views? I would like to hide some group of views independent of their position in the layout tree.
I think that you will need to iterate through all of the views in your layout, looking for the android:id you want. You can then use View setVisibility() to change the visibility. You could also use the View setTag() / getTag() instead of android:id to mark the views that you want to handle. E.g., the following code uses a general purpose method to traverse the layout:
// Get the top view in the layout.
final View root = getWindow().getDecorView().findViewById(android.R.id.content);
// Create a "view handler" that will hide a given view.
final ViewHandler setViewGone = new ViewHandler() {
public void process(View v) {
// Log.d("ViewHandler.process", v.getClass().toString());
v.setVisibility(View.GONE);
}
};
// Hide any view in the layout whose Id equals R.id.textView1.
findViewsById(root, R.id.textView1, setViewGone);
/**
* Simple "view handler" interface that we can pass into a Java method.
*/
public interface ViewHandler {
public void process(View v);
}
/**
* Recursively descends the layout hierarchy starting at the specified view. The viewHandler's
* process() method is invoked on any view that matches the specified Id.
*/
public static void findViewsById(View v, int id, ViewHandler viewHandler) {
if (v.getId() == id) {
viewHandler.process(v);
}
if (v instanceof ViewGroup) {
final ViewGroup vg = (ViewGroup) v;
for (int i = 0; i < vg.getChildCount(); i++) {
findViewsById(vg.getChildAt(i), id, viewHandler);
}
}
}
You can set same tag for all such views and then you can get all the views having that tag with a simple function like this:
private static ArrayList<View> getViewsByTag(ViewGroup root, String tag){
ArrayList<View> views = new ArrayList<View>();
final int childCount = root.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = root.getChildAt(i);
if (child instanceof ViewGroup) {
views.addAll(getViewsByTag((ViewGroup) child, tag));
}
final Object tagObj = child.getTag();
if (tagObj != null && tagObj.equals(tag)) {
views.add(child);
}
}
return views;
}
As explained in Shlomi Schwartz answer. Obviously this is not as useful as css classes are. But this might be a little useful as compared to writing code to iterate your views again and again.

How can I get an ActionBar's TextView?

I can get an ActionBar's view using getCustomView. Is there a way to get its TextView from that?
Not in any way that is going to be reliable across OS versions and devices.
If you are attempting to set the title of the action bar, please use setTitle() on ActionBar. If you are trying to style the title, you should be able to do that via a theme.
Or, hide the title and render your own via setCustomView().
Try recursively? (might not be a good solution though!)
static List<TextView> textViews = new ArrayList<TextView>();
public static <T> void searchRecursively(View parent, Class<T> clazz)
{
if(clazz.isInstance(parent)) textViews.add(clazz.cast(parent));
if(parent instanceof ViewGroup)
{
ViewGroup vg = (ViewGroup) parent;
int count = vg.getChildCount();
for(int i = 0; i < count; i++)
{
View v = vg.getChildAt(i);
searchRecursively(v);
}
}
}
Use it like:
searchRecursively(theView, TextView.class);

findViewById to return array of Views

I have the same View inflated (from XML) multiple times. When I call findViewById(R.id.my_layout).setVisibility(View.GONE) I want to apply it on all such views.
How do I do that?
There isn't a version of findViewById() that returns all matches; it just returns the first one. You have a few options:
Give them different ids so that you can find them all.
When you inflate them, store the reference in an ArrayList, like this:
ArrayList<View> mViews = new ArrayList<View>();
Then when you inflate:
LayoutInflater inflater = getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mViews.add(inflater.inflate(R.layout.your_layout, root));
Then when you want to hide them:
for (View v : mViews) { v.setVisibility(View.GONE); }
Depending on what you're doing with these Views, the parent layout may have a way of accessing them. E.g., if you're putting them in a ListView or some such. If you know the parent element you can iterate through the children:
ViewGroup parent = getParentSomehow();
for (int i = 0; i < parent.getChildCount(); ++i) {
View v = parent.getChildAt(i);
if (v.getId() == R.id.my_layout) {
v.setVisibility(View.GONE);
}
}
If the above options don't work for you, please elaborate on why you're doing this.
Modify on the View that holds the inflated layout.
E.g:
If you have
View v = inflater.inflate(.... );
you change the visibility onto this view. v.setVisibility(View.GONE);

Categories

Resources