C#-Xamarin的Android项目开发(一)——建立项目

建立项目android

使用Xamarin开发安卓项目,首先须要安装VS2017以上版本。由于VS2017以上的版本,能够直接建立Xamarin项目。git

另外用Xamarin开发安卓项目,还须要使用Intel的CPU,而且得是双核以上的CPU,由于调试时,须要使用电脑的虚拟化,奔腾4之类的CPU是不支持虚拟化的。github

下面咱们建立KibaXamarin_Android项目,以下图:sql

点击肯定后,会弹出一个选择模板的窗体,这里咱们选择一个空白应用,而且选择最小安卓版本号为4.4,以下图:json

 点击OK后,项目建立完成,解决方案内容以下图app

解决方案中重要的文件及文件夹以下:异步

Resources/layout/activity_main.axml:该文件为主页面。ide

MainActivity.cs:该文件为主页面对应的后台页面,也咱们进行逻辑操做或者调用逻辑操做的地方。函数

Resources/value/xxx.xml:value文件夹下主要存储经常使用的值,相似于咱们C#中的const常量。工具

其余文件夹及文件暂时忽略。

在Resources文件夹里,咱们能够发现,没有存储图片的地方,那么,咱们建立一个文件夹drawable用来存储图片。

为何用drawable存图片?答案很简单,由于网上的开源样式里的图片大多放在了drawable里,创建一个这样的文件夹,绝对会减小咱们的工做量。

接下来,咱们看一下咱们的核心文件,MainActivity,代码以下:

[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState); 
        // Set our view from the "main" layout resource
        SetContentView(Resource.Layout.activity_main);
    }
}

 首先,咱们看第一行的特性,这里有三个属性赋值,含义以下:

Label:页面的标题。

Theme:页面的样式。

MainLauncher:是不是主窗体,该属性在项目只能给一个页面。

而后,咱们能够看到咱们的主页面MainActivity继承了AppCompatActivity,这里的AppCompatActivity是一个继承了Activity的子类,咱们暂时先不了解它,由于咱们即将建立一个继承Activity的BaseActivity,后续的[Activity]也将继承BaseActivity。

接下来咱们看到了OnCreate方法,这里咱们须要了解下Activity的生命周期,OnCreate是Activity的第一个触发的方法,能够暂时先理解为Activity的构造函数。

OnCreate方法里咱们看到了SetContentView(Resource.Layout.activity_main),根据字面咱们先简单的理解该方法为设置内容视图。

能够看到咱们在设置内容视图的时候,去资源里找了一个页面;也就是说,在Android中,视图是倒装的,现有Activity而后由Activity来控制要导入那个页面视图显示。

为了更好的寻找视图,咱们将视图名和活动名进行统一,修改页面的名为MainActivity,而后再从新设置内容视图。(这里有个编译器的BUG,咱们更名之后,编译器并无同步,因此咱们须要清理一下,再从新生成,若是还不成功,就删除obj文件夹,再从新生成)

BaseActivity

经过上面的描述,咱们初步了解了Xamarin的Android项目。

如今咱们一块儿建立一个BaseActivity。

首先咱们须要为BaseActivity封装一些提示信息的方法,让继承该类的活动能够更简单的调用提示。

而后咱们封装寻找资源的方法;在Android项目里是由活动调用视图,即先有活动后有视图,因此在活动里找页面的控件也是倒装的,那么这个寻找控件的方法就相对代码会比较多,因此咱们简单封装一下。

接下来咱们在封装一些跳转活动、建立服务、异步调用等基础方法;BaseActivity代码以下:

[Activity(Label = "KibaXamarin_Android")]
public class BaseActivity : Activity
{
    public void ShowActivity<T>() where T : Activity
    {
        Intent intent = new Intent(this, typeof(T));
        StartActivity(intent);
    }
    public void OpenService<T>() where T : Service
    {
        Intent intent = new Intent(this, typeof(T));
        StartService(intent);
    }

    #region  各类提示信息
        public void ShowToast(string msg)
        {
            Toast.MakeText(this, msg, ToastLength.Short).Show();
        }
       
        private AlertDialog dialog;
        public AlertDialog InitDialog(string msg, Action<AlertDialog> comfirmCallback, Action<AlertDialog> cancelCallback)
        {
            AlertDialog cdialog;
            //构造器
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            //标题
            builder.SetTitle("提示");
            //图标
            //builder.SetIcon(android.R.drawable.btn_dialog);
            //内容
            builder.SetMessage(msg);
            //setPositiveButton(表示按钮的文本,表示单击按钮触发单击事件)
            builder.SetPositiveButton("OK", new EventHandler<DialogClickEventArgs>((s, e) =>
            {
                if (comfirmCallback != null)
                {
                    comfirmCallback(dialog);
                }
            }));
            builder.SetNegativeButton("Cancel", new EventHandler<DialogClickEventArgs>((s, e) =>
            {
                if (cancelCallback != null)
                {
                    cancelCallback(dialog);
                }
            }));
            //builder.SetNeutralButton("稍后提醒", new EventHandler<DialogClickEventArgs>((s, e) => { }));
            cdialog = builder.Create();//构建dialog对象

            return cdialog;
        }

        public void ShowAlert(string msg, Action<AlertDialog> comfirmCallback = null, Action<AlertDialog> cancelCallback = null)
        {
            if (comfirmCallback == null)
            {
                cancelCallback = (d) => { dialog.Dismiss(); };
            }
            if (cancelCallback == null)
            {
                cancelCallback = (d) => { dialog.Dismiss(); };
            }
            dialog = InitDialog(msg, comfirmCallback, cancelCallback);
            if (dialog != null && !dialog.IsShowing)
            {
                dialog.Show();
            }
        }

        public void NotifyMessage(string message, string title = "消息")
        { 
            NotificationManager manager = (NotificationManager)GetSystemService(Context.NotificationService);  // 在Android进行通知处理,首先须要重系统哪里得到通知管理器NotificationManager,它是一个系统Service。  
            PendingIntent pendingIntent = PendingIntent.GetActivity(this, 0,
                    new Intent(this, typeof(MainActivity)), 0);
            Notification notify1 = new Notification();
            notify1.Icon = Resource.Drawable.logo;
            notify1.TickerText = JaveString("您有新短消息,请注意查收!");
            notify1.When = DateTime.Now.ToFileTime();
            notify1.SetLatestEventInfo(this, title, message, pendingIntent);
            notify1.Number = 1;
            notify1.Flags |= NotificationFlags.AutoCancel; // FLAG_AUTO_CANCEL代表当通知被用户点击时,通知将被清除。  
                                                           // 经过通知管理器来发起通知。若是id不一样,则每click,在statu那里增长一个提示  
            manager.Notify(1, notify1); 
        }
        public static Java.Lang.String JaveString(string str)
        {
            return new Java.Lang.String("您有新短消息,请注意查收!");
        }
        #endregion

    #region 寻找资源
        public T FindControl<T>(string name) where T : View
        {
            return FindViewById<T>(GetCode(name));
        }

        public T FindControl<T>(string name, Action callBack) where T : View
        {
            View view = FindViewById<T>(GetCode(name));
            view.Click += (s, e) =>
            {
                callBack();
            };
            return FindViewById<T>(GetCode(name));
        } 

        public int GetCode(string name)
        {
            var R = this.Resources;
            var code = (typeof(Resource.Id)).GetFields().FirstOrDefault(f => f.Name == name).GetValue(R);
            return (int)code;
        }
        #endregion

    #region 异步调用
        public void AsyncLoad(Action action)
        {
            IAsyncResult result = action.BeginInvoke((iar) =>
            {
            }, null);
        }
        public void AsyncLoad(Action action, Action callback)
        {
            IAsyncResult result = action.BeginInvoke((iar) =>
            {
                this.RunOnUiThread(callback);
            }, null);
        }

        public void AsyncLoad<T>(Action<T> action, T para, Action callback)
        {
            IAsyncResult result = action.BeginInvoke(para, (iar) =>
            {
                this.RunOnUiThread(callback);
            }, null);
        }
        public void RunOnUi(Action action)
        {
            ((BaseActivity)this).RunOnUiThread(() => { action(); });//回UI线程
        }
        #endregion

    #region 获取数据
        public void GetRest(string url, Action<JsonValue> callback)
        {
            Task.Run(() =>
            {
                try
                {
                    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
                    request.ContentType = "application/json";
                    request.Method = "GET";
                    using (WebResponse response = request.GetResponse())
                    {
                        using (Stream stream = response.GetResponseStream())
                        {
                            JsonValue jsonDoc = JsonObject.Load(stream);
                            callback(jsonDoc);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log.Debug("BaseActivity", $"Exception at GetRest" + ex.Message);
                }
            });

        }
        #endregion 
}

视图MainActivity.axml

Android视图是有xml语法来编写的,其中一些语法定义是很奇葩,但也只能去适应,没有别的办法。好比Android里定义ID名是这样的:android:id="@+id/btn_search"。我每次看这个@+id都感受很奇葩,哈哈。

Xamarin的视图和Android的视图是同样的,因此咱们尽可上网找一些资源来使用。

咱们先修改视图代码以下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#ffffffff">
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/title_background"
        android:paddingLeft="5dip"
        android:paddingRight="5dip"
        android:paddingTop="5dip"
        android:paddingBottom="5dip"
        android:gravity="center_vertical">
        <LinearLayout
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="2">
            <TextView
                android:textAppearance="?android:textAppearanceMedium"
                android:layout_gravity="center_vertical"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="KibaXamarin_Android"
                android:textColor="#ffffffff" />
            <ImageView
                android:src="@drawable/ic_arrow_down"
                android:layout_gravity="center_vertical"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="#ffffffff" />
        </LinearLayout>
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="5">
            <ImageButton
                android:src="@drawable/toolbar_upload_photo_normal"
                android:layout_gravity="right|center_vertical"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/btn_weight" />
        </FrameLayout>
    </LinearLayout>
    <LinearLayout
        android:gravity="center"
        android:orientation="horizontal"
        android:background="@drawable/search_bar_background"
        android:padding="6.0dip"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <Button
            android:textAppearance="?android:textAppearanceMedium"
            android:gravity="left|center"
            android:id="@+id/btn_search"
            android:layout_width="0.0dip"
            android:layout_height="wrap_content"
            android:hint="\u0020Click Me"
            android:drawableLeft="@drawable/ic_btn_search"
            android:layout_weight="1.0" />
    </LinearLayout>
    <GridView
        android:paddingTop="20dip"
        android:gravity="center"
        android:id="@+id/my_grid"
        android:layout_width="fill_parent"
        android:layout_height="0.0px"
        android:layout_marginTop="0.0dip"
        android:horizontalSpacing="10.0dip"
        android:verticalSpacing="20.0dip"
        android:stretchMode="columnWidth"
        android:columnWidth="60.0dip"
        android:numColumns="3"
        android:layout_weight="1.0"
        style="@style/CustomGridView" />
</LinearLayout>

Xamarin的简单应用

如今,咱们的页面和BaseActivity已经完成,让咱们一块儿作一些简单的使用把。

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);  
    SetContentView(Resource.Layout.MainActivity);
    Button btn_search = this.FindControl<Button>("btn_search");
    btn_search.Click += (s, e) =>
    {
        this.ShowToast("Click Me");
    }; 
}

如上代码所示,咱们找到了Button-btn_search,并为他建立了单击事件;看起来还不错,代码还算简洁。

由于BaseActivity里寻找控件的方法里,还封装了Click方法,因此咱们还能够这样使用:

Button btn_search = this.FindControl<Button>("btn_search", () => { this.ShowToast("Click Me"); });

Xamarin的调试

Xamarin的调试很是简单,只要配置好模拟器按F5调试就能够了,由于VS2017集成了Emulator模拟器,因此咱们只要运行调试,就会自动帮咱们启动模拟器。

模拟器是配置很简单,在工具里找到Android—Android设备管理器,以下图:

而后作一些简单配置修改,以下图:

模拟器配置好之后,在调试启动的选项中,就会增长这个模拟器的选项,以下图:

接下来就很简单了,只要直接点击运行就能够了。

运行结果以下图:

从图中咱们能够看到,咱们的安装项目已经成功运行了,而且执行了点击事件。

到此,这个简单的安卓项目已经建立完成了,下一篇文章,将介绍Xamarin中如何使用安卓控件。

----------------------------------------------------------------------------------------------------

代码已经传到Github上了,欢迎你们下载。

Github地址:https://github.com/kiba518/KibaXamarin_Android

----------------------------------------------------------------------------------------------------

注:此文章为原创,任何形式的转载都请联系做者得到受权并注明出处!
若您以为这篇文章还不错,请点击下方的推荐】,很是感谢!

 

相关文章
相关标签/搜索