【问题标题】:How to set fontFamily for the entire Xamarin.Android application in a single place?如何在一个地方为整个 Xamarin.Android 应用程序设置 fontFamily?
【发布时间】:2019-12-31 10:44:31
【问题描述】:

我想为工具栏的文本、按钮、TextViews 和 Xamarin.Andrid 应用程序的所有文本设置 fontFamily。我如何在一个地方做到这一点?我尝试将以下内容放在Base application theme 中的styles.xml 中:

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    .....
    <item name="fontFamily">@drawable/Exo2_ExtraBold</item>
    .....
</style>

但它只改变了MainActivityfontFamily,我猜这是因为只有那个活动上面有Theme = "@style/AppTheme" 属性。如果我将该属性放在其余活动之上,我想它也会起作用,但是是否有一种更简单的方法可以让所有应用程序在应用程序的一个位置设置一个fontFamily?此外,我将.otf 文件放在drawables 文件夹中,我尝试将其放在手动创建的font 文件夹中,但在尝试重建解决方案时出现错误。所以我也想知道如何解决这个问题,将.oft 放在正确的文件夹中。

【问题讨论】:

    标签: xamarin.android set font-family


    【解决方案1】:

    在android中使用自定义字体最简单的方法是使用Calligraphy,对于Xamarin,你可以使用CallygraphyXamarin

    1. 复制您的自定义字体,例如:my-custom-font.ttf,到fonts 目录,在assets 目录内。
    2. 添加CallygraphyXamarinnuget 包Install-Package CallygraphyXamarin

    3. 创建一个类,例如:Startup 并添加以下内容:

    [Application]
    public class Startup : Application
    {   
        public Startup(IntPtr javaReference, JniHandleOwnership transfer)
            : base(javaReference, transfer) { }
    
        public override void OnCreate()
        {
            base.OnCreate();
    
            CalligraphyConfig.InitDefault(
                new CalligraphyConfig.Builder()
                    .SetDefaultFontPath("fonts/my-custom-font.ttf")
                    .SetFontAttrId(Resource.Attribute.fontPath)
                    .Build()
            );      
        }
    }
    
    1. 在您的Activities 添加以下代码,您就可以开始了。
    protected override void AttachBaseContext(Context context)
    {
        base.AttachBaseContext(Calligraphy.CalligraphyContextWrapper.Wrap(context));
    }
    

    您可以创建一个基础活动以避免将上述代码添加到每个活动。

    更新:

    为了改变工具栏的字体,如果你不想添加Textview作为它的标题,你应该添加以下样式到style.xml

    <style name="ToolbarTheme" parent="@style/ThemeOverlay.AppCompat.ActionBar">
        <item name="fontPath">fonts/custom-font.ttf</item>
    </style>
    

    并将这种样式应用到工具栏,如下所示:

    <android.support.v7.widget.Toolbar
        ...
        android:theme="@style/ToolbarTheme"/>
    

    Related github issue

    【讨论】:

    • AttachBaseContext 方法中 Calligraphy.CalligraphyContextWrapper.Wrap(context) 未被识别为方法,因此我将 Calligraphy.Xamarin.CalligraphyContextWrapper.Wrap(context) 改为。当我运行应用程序时,我在MainActivity(这是我的主启动器)的SetContentView(Resource.Layout.MainActivity) 行收到以下错误:System.InvalidCastException: Specified cast is not valid.
    • 我发布了我的MainActivity.cs 作为对我问题的回答。
    • 我所有的活动除了MainActivity 都有Toolbar 和标题。但它的fontFamily 没有改变。我该怎么做才能改变它?
    • 是的,新包有效。我没有对Toolbar 应用任何样式,这里是:&lt;Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="?attr/actionBarSize" android:background="@color/appColor" android:title = "Congreso" android:titleTextColor = "#FFFFFF" android:navigationIcon="@drawable/ic_toolbar_back_button"/&gt; 也不是styles.xml
    • 我有 3 个问题。 Startup 类是否仅用于为整个应用程序设置 fontFamily,或者我可以在其中放入任何初始化逻辑?我的第二个问题是,如果我把 AttachBaseContext 方法放在 BaseActivity 中,我在它上面放什么评论,它有什么作用?我的第三个问题,我的MainActivity 继承自AppCompatActivity,所有其他活动都继承自Activity。如果我创建从AppCompatActivity 继承的BaseActivity 并使MainActivity 和其余活动继承BaseActivity,这会是一个问题吗?
    【解决方案2】:

    当我们创建一个新的Activity时,它的超类默认是Activity。所以我们应该手动把它改成AppCompatActivity。并添加行Theme = "@style/AppTheme"

    using Android.Support.V7.App;
    
    [Activity(Label = "Activity1", Theme = "@style/AppTheme")]
    public class Activity1 : AppCompatActivity
    

    【讨论】:

    • 我所有的活动默认都继承自AppCompatActivity。所以我必须在所有活动之上添加Theme = "@style/AppTheme"?没有其他更短的方法吗?
    • 也许你可以创建一个BaseActivity
    • 然后把Theme = "@style/AppTheme"放在上面?
    • 是的,你可以试试。如果它不起作用,也许你必须在每个 Activity 上添加它。
    【解决方案3】:

    这是我的MainActivity

    [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true, ScreenOrientation = ScreenOrientation.Portrait)]
    public class MainActivity : AppCompatActivity
    {
        Button informationBtn;
        ImageButton congressImageBtn;
        ImageButton exhibitionAreaImageBtn;
        ImageButton facebookImageBtn;
        ImageButton twitterImageBtn;
        ImageButton linkedinImageBtn;
    
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
    
            SetContentView(Resource.Layout.MainActivity);
    
            FindViews();
    
            BindClickEvents();
    
        }
    
        /// <summary>
        /// Method to find the views
        /// </summary>
        private void FindViews()
        {
            informationBtn = FindViewById<Button>(Resource.Id.informationBtn);
            congressImageBtn = FindViewById<ImageButton>(Resource.Id.congressImageBtn);
            exhibitionAreaImageBtn = FindViewById<ImageButton>(Resource.Id.exhibitionAreaImageBtn);
            facebookImageBtn = FindViewById<ImageButton>(Resource.Id.facebookImageBtn);
            twitterImageBtn = FindViewById<ImageButton>(Resource.Id.twitterImageBtn);
            linkedinImageBtn = FindViewById<ImageButton>(Resource.Id.linkedinImageBtn);
        }
    
        /// <summary>
        /// Method to bind the click events
        /// </summary>
        private void BindClickEvents()
        {
            informationBtn.Click += delegate
            {
                StartActivity(typeof(ContactInformationActivity));
                Finish();
            };
    
            congressImageBtn.Click += delegate
            {
                StartActivity(typeof(CongressActivity));
                Finish();
            };
    
            exhibitionAreaImageBtn.Click += delegate
            {
                StartActivity(typeof(ExhibitionAreaActivity));
                Finish();
            };
    
            facebookImageBtn.Click += delegate
            {
                var uri = Android.Net.Uri.Parse("https://www.facebook.com/");
                var intent = new Intent(Intent.ActionView, uri);
                StartActivity(intent);
            };
    
            twitterImageBtn.Click += delegate
            {
                var uri = Android.Net.Uri.Parse("https://twitter.com/");
                var intent = new Intent(Intent.ActionView, uri);
                StartActivity(intent);
            };
    
            linkedinImageBtn.Click += delegate
            {
                var uri = Android.Net.Uri.Parse("https://www.linkedin.com/");
                var intent = new Intent(Intent.ActionView, uri);
                StartActivity(intent);
            };
        }
    
        protected override void AttachBaseContext(Context context)
        {
            base.AttachBaseContext(Calligraphy.Xamarin.CalligraphyContextWrapper.Wrap(context));
        }
    
    }
    

    【讨论】:

    • 是的,是一样的。唯一的区别是我放了fonts/Exo2_ThinItalic.otf 而不是fonts/my-custom-font.ttf。这是唯一的区别。
    猜你喜欢
    • 1970-01-01
    • 2019-12-16
    • 1970-01-01
    • 1970-01-01
    • 2019-01-07
    • 1970-01-01
    • 2012-07-31
    • 1970-01-01
    相关资源
    最近更新 更多