Xamarin AppCompat textview custom - android

After updating Android Support Libary v7 AppCompat
I'm not able to change style to the title and the following
is not wotking anymore:
int myTitleId = Resources.GetIdentifier("action_bar_title", "id", "android");
TextView barTitle = FindViewById<TextView>(myTitleId);
barTitle.SetTypeface(FontFactory.GetMyFont(this), TypefaceStyle.Normal);

That's because AppCompat now uses a ToolBar widget as replacement for ActionBar. ToolBar creates a TextView instance for the title on-the-fly; if you dig into the (android.support.v7.widget.)ToolBar code, you'll find something like this:
mTitleTextView = new TextView(context);
(Refer to line 607 of android.support.v7.widget.ToolBar in appcompat-v7-23.0.1-sources.jar)
More importantly, no id is ever assigned to the view. This can also easily be seen by inspecting the view hierarchy:
That TextView that you see is the one that holds the title. The id is a generated value and not predefined (like i.e. the one for the ActionBarContainer), which means you can no longer look it up through some sort of static reference.
That explains why your code, which does an id-lookup-by-name, no longer works: the action_bar_title id is simply no longer being used here.
There are several solutions to make setting a custom font to the ActionBar title work again. The cleanest is probably to leverage the fact that setTitle() takes a CharSequence, which means you can attach a custom typeface span to it that enables the custom font and/or style to work. Doing this is some sort of a 'base' Activity would probably make most sense.
You can of course also iterate over the local view hierarchy, starting at ToolBar, but I'd say that's not quite as robust and prone to suffer from future changes (like your current code ;)).
Alternatively, consider using a library to simplify dealing with applying custom fonts. Calligraphy is usually my first stop for this.

After integrating the new Toolbar this is how I changed style.
inside protected override void OnCreate(Bundle bundle) of my Activity (that now extends AppCompatActivity)
where before there was the previous code now I have:
toolbar = FindViewById<Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
var f = toolbar.Class.GetDeclaredField("mTitleTextView");
f.Accessible = true;
var barTitle = (TextView)f.Get(toolbar);
barTitle.SetTypeface(FontFactory.GetMyFont(this), TypefaceStyle.Normal);
I needed also to add this on the top:
using Java.Lang; //for the reflection
using Toolbar = Android.Support.V7.Widget.Toolbar;
and in the layout.axml I included the toolbar.axml in this way:
//...
<include
android:id="#+id/toolbar"
layout="#layout/toolbar" />
//...

Related

How To Change Included Toolbar Title And Drawable?

I have a hard time finding on how to change the Toolbar title and it's drawable in every and each Activity.
There is something on Android Documentation that states that to minimize APK size. It is recommended to re-used components.
I create a separate layout, and <include layout=""/> to each of my Activities like Help, About , and etc. I also put android:label="Title" on Manifest File.
Toolbar.xml
My Main:
How do I access this included Toolbar DRAWABLE and TITLE in my Activities ?
Update: I removed ActionBar .
You are using Toolbar. So no need to do anything with ActionBar. Just set your Toolbar as supportActionBar. Then set title and icon to your Toolbar.
Use the below code:
mToolbar = (Toolbar)findViewById(R.id.Toolbar);
setSupportActionBar(mToolbar);
setTitle("About");
getSupportActionBar.setIcon(R.id.ic_arrow_back_black_24dp);
And, Remove all your mActionBar codes. Hope this helps.
well you set the support action to your custom toolbar,yet you ignore it and use mActionBar, see where i am going with this? setIcon , and setTitle should all be called relative to your custom toolbar.

Android checkboxes added by code don't have the right appearance?

I've got a really basic app in which I'm trying to insert dynamic checkboxes, and I can get them to appear, but they're not showing with the correct styling.
See below - Foo is in the LinearLayout by definition; Bar is being added programmatically. Foo is showing with a grey box for the check, Bar is showing with a white box.
Link to image...
Here's the code that's creating these:
for (Integer i=0; i < arArray.length;i++) {
CheckBox cb = new CheckBox(getApplicationContext());
cb.setText("Bar");
cb.setTextColor(getResources().getColor(android.R.color.black));
cb.setOnCheckedChangeListener(clListener);
llDeckChecks.addView(cb);
}
I've tried setting the drawable to some android.R.drawable types, but nothing matches the Foo checkbox, so I'm entirely stumped at this point.
AppCompat replaces the default widgets with tinted, consistent styles, as mentioned in the Android Support Library 22.1 blog post:
This is done automatically when inflating layouts - replacing Button with AppCompatButton, TextView with AppCompatTextView, etc. to ensure that each could support tinting.
If you'd like to create these programmatically, you can use AppCompatCheckBox in place of Checkbox in your code, passing in your current Context such as your AppCompatActivity.
Note: it is very important to not use getApplicationContext() as it does not have the styling information required.
You should use the activity context to create the button instead of the application context. If you use getApplicationContext() it does not extend ContextThemeWrapper.
Try changing
CheckBox cb = new CheckBox(getApplicationContext());
to
CheckBox cb = new CheckBox(YourActivity.this); // or getActivity() if in a fragment.
Use cb.setButtonDrawable(R.drawable.cbOutline); where "cbOutline" is your drawable for the checkboxes outline you defined in your XML.

How to change existing TextView style in action

I have some intent with set of TextViews and a Button. If user clicks the button and there is some error I want to change look of one TextView. E.g. change the border to red and make font bold. I wrote a style for it but I have not found method setStyle on the TextView. After some self study I realized that Android does not support setting the style programmatically. There are some workarounds, when you create the intent source. But my intent already exists, it seems odd to recreate it.
Could you tell me the proper way?
use the workaround and create the TextView again
forget the styles and use java methods to decorate existing TextView
something else
Changing the style of the textview directly does not work as you know. But you can create a second textview with other styles in your layout, which you can show up if needed.
Just add this xml attribute android:visibility="gone" to the second textview, so this second textview is not displayed at first, but available.
When you now want to change the style of your textview, you simple need to swap the two textviews by hidding the first one and showing the second one
textView1.setVisibility(View.GONE);
textView2.setVisibility(View.VISIBLE);
I used these two answers to make it work:
https://stackoverflow.com/a/5488652/1639556
https://stackoverflow.com/a/14195090/1639556
and the code is:
ViewManager parent = (ViewManager) unknown.getParent();
parent.removeView(unknown);
TextView newUnknown = (TextView)getLayoutInflater().inflate(R.layout.tvtemplate, null);
newUnknown.setId(unknown.getId());
parent.addView(newUnknown, unknown.getLayoutParams());
unknown = newUnknown;
You can try using setTextAppearance() on the textview. The link is: setTextAppearance
Your style will need TextAppearance.SomeThing.SomeOtherThing as the parent.
Use R.style.YourStyleName as the integer argument.

ActionBar with support library and Fragments overlay content

I added the android-support-library-v7-appcompat to my project to support ActionBar from API level 7 above.
It works like a charm on android 4.0+ and also on android 2.3 with a normal Activity that has setContentView in onCreate, but when the activity is loading an Fragment in onCreate the ActionBar gets overlapped with the content of my layout. At all other scenarios the ActionBar works well.
Here is some code:
class AssetsActivity extends ActionBarActivity{
#Override
protected void onCreate(Bundle arg0)
{
super.onCreate(arg0);
OpenLocalFragment assets = OpenLocalFragment.newInstance(index);
assets.setArguments(getIntent().getExtras());
getSupportFragmentManager().beginTransaction()
.add(android.R.id.content, assets).commit();
}
}
The theme of this activity is set in the manifest to:
#style/Theme.AppCompat
An this is the result on android 2.3 (on 4.0+ the ActionBar shows well)
You can se that the first lisview item is overlaping the ActionBar(White round icon and title "My activity")
It is possible that i found a bug in the support library, it is released only for 2 days now?
Thanks to all.
Edit:
This is now officially fixed and released in the Support Library v19.
As JJD commented below, you can use normally android.R.id.content with appcompat-v7 r.19.0.0 or newer. The home button works too.
With other words: The workaround below is no more needed if you use version 19.0.0 or newer.
I got the answer at code.google.com. i've made a summary from frederic's answer:
For pre ICS devices you must use:
R.id.action_bar_activity_content
instead of
android.R.id.content
R.id.action_bar_activity_content is a new id used in layout for displaying app content, it would appear that it replace android.R.id.content when you use support v7 appcompat ActionBarActivity.
You can use this code to retrieve the correct id of the activity content :
public static int getContentViewCompat() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH ?
android.R.id.content : R.id.action_bar_activity_content;
}
Thanks to frederic
Another alternative if you do not want to modify the source code of android-support-library-v7-appcompat is to add an empty layout in the layout xml file such as:
<LinearLayout
android:id="#+id/content_view"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
and make the fragment call to add to that layout instead:
ft.add(R.id.content_view, mFragment, mTag);
Seems a bit late to contribute but I had the same problem and haven't seen the answer here....
Check your styles.xml file, there might be an xml attribute for overlaying the actionbar set to true ie
true
The whole entry looks something like this
<item name ="actionBarTabTextStyle" > #style/TabTextStyle</item>
<item name = "windowActionBarOverlay">true</item>
If that is the case then just change the value of "windowActionBarOverlay" to false.
Add a extra empty list header with the size of the actionbar. Should be a good workaround.

In android How to applying font for whole application?

I want to apply some font say Times New Roman to only my application.
Not to the whole system and not to specific view. As far I know
to apply font to specific view we store font file in asset folder and get into the application as follow.
1] Typeface mFace = Typeface.createFromAsset(getContext().getAssets(),
"fonts/samplefont.ttf");
textView.setTypeface(mFace);
2] To apply font to whole application I can replace the DroidSans.ttf file with my font file.
I can use first way to apply font to my application but It won't be a good solution because I need to modify everywhere and I don't want to do that if there is any better way is available.
I made a custom textview widget and in the constructors made a call to this code:
public static void SetCustomFont (TextView t, String fontName, Context c) {
Typeface tf = Typeface.createFromAsset(c.getAssets(),
fontName);
t.setTypeface(tf);
}
I'm using the same font over the whole application so I put the fontName in the constuctor and then did a global Find/Replace for TextView
Android does not provide much in the way of support for applying fonts across the whole app (see this issue). You have 4 options to set the font for the entire app:
Option1: Apply reflection to change the system font
Option2: Create and subclass custom View classes for each View that needs a custom font
Option3: Implement a View Crawler which traverses the view hierarchy for the current screen
Option4: Use a 3rd party library.
Details of these options can be found here.
Check this to define fonts styles. In addition, you can refer to this style from your manifest file at the app level
<application
android:theme="#style/Theme1">

Categories

Resources