Xamarin.Forms ChatKit +Socket实现即时通讯

Xamarin.Forms ChatKit 的使用 快速搭建即时通讯 UI

大家完成好,本期为大家实现 Android 端 SocketChat 的实现(需要源码请滑到最下面有博主通讯方式)

项目介绍:
ChatKit 控件来源:
https://github.com/jingliancui/XamarinFormsChatKitSample
通信组件:Socket

组成部分:服务端(PC,Winforms) 客户端(PC,Winfrom,Xamarin.Forms Android)

画个简单的实现草图:
在这里插入图片描述
看过这张图相信会有点轻微的理解:
下面看代码实现:

第一步安装 依赖包

安装 NewGet 依赖包:
Install-Package XamarinLibrary.Xamarin.Android.ChatKit -Version 0.3.3
这个是 类似 QQ的聊天 UI

第二步 编写UI

在这里插入图片描述
在这里插入图片描述
代码量太多 就不一一展示
贴上重要代码:

Socket Client Code:

创建 一个单例XamarinSockectClient 类 防止客户端重复创建

0000100020003 在线列表协议头 ,

000200030006 好友消息协议头

 /// <summary>
    /// Sockect通讯客户端  
    /// </summary>
    public class XamarinSockectClient
    {

        private static XamarinSockectClient _Singleton = null;
        public static XamarinSockectClient CreateInstance()
        {
            if (_Singleton == null)
            {
                _Singleton = new XamarinSockectClient();
            }
            return _Singleton;
        }
        public static XamarinSockectClient CreateInstance(string Ip, string Port)
        {
            if (_Singleton == null)
            {
                _Singleton = new XamarinSockectClient(Ip, Port);
            }
            return _Singleton;
        }

      

        public string ServerIp = "192.168.1.105";
        public string ServerPort = "9000";
        //public XamarinSockectClient()
        //{
        //    XamarinConnectToServer();
        //}

        public XamarinSockectClient(string Ip = "192.168.1.105", string Port = "9000")
        {
            ServerIp = Ip;
            ServerPort = Port;
            XamarinConnectToServer();
        }
        Socket socketClient = null;
        Thread threadClient = null;

        public const int SendBufferSize = 2 * 1024;
        public const int ReceiveBufferSize = 8 * 1024;

        private void XamarinConnectToServer()
        {
            //定义一个套字节监听  包含3个参数(IP4寻址协议,流式连接,TCP协议)
            socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //获取文本框输入的服务端IP和Port
            IPAddress serverIPAddress = IPAddress.Parse(ServerIp);
            int serverPort = int.Parse(ServerPort);
            IPEndPoint endpoint = new IPEndPoint(serverIPAddress, serverPort);
            //向指定的ip和端口号的服务端发送连接请求 用的方法是Connect 不是Bind
            socketClient.Connect(endpoint);
            //创建一个新线程 用于监听服务端发来的信息
            threadClient = new Thread(RecMsg);
            //将窗体线程设置为与后台同步
            threadClient.IsBackground = true;
            //启动线程
            threadClient.Start();
            //登录成功
            //txtMsg.AppendText("已与服务端建立连接,可以开始通信...\r\n");
            // btnConnectToServer.Enabled = false;
        }


        /// <summary>
        /// 接受服务端发来信息的方法
        /// </summary>
        private void RecMsg()
        {
            while (true) //持续监听服务端发来的消息
            {
                string strRecMsg = null;
                int length = 0;
                byte[] buffer = new byte[SendBufferSize];
                try
                {
                    //将客户端套接字接收到的字节数组存入内存缓冲区, 并获取其长度
                    length = socketClient.Receive(buffer);
                }
                catch (SocketException ex)
                {
                    // txtMsg.AppendText("套接字异常消息:" + ex.Message + "\r\n");
                    //    txtMsg.AppendText("服务端已断开连接\r\n");
                    break;
                }
                catch (Exception ex)
                {
                    // txtMsg.AppendText("系统异常消息: " + ex.Message + "\r\n");
                    break;
                }
                //将套接字获取到的字节数组转换为人可以看懂的字符串
                strRecMsg = Encoding.UTF8.GetString(buffer, 0, length);             
               string[] ServerValue= strRecMsg.Split('*');
                switch (ServerValue[0])
                {
                    case "0000100020003":
                        if (DevHelp.DeviceHelp.devDelegateUpdateUi != null)
                        {                     
                            DevHelp.DeviceHelp.devDelegateUpdateUi.InitUI(ServerValue[1]);                     
                        }
                        break;
                    case "000200030006":
                        if (DevHelp.DeviceHelp.devDelegateMessagesList != null)
                        {
                            DevHelp.DeviceHelp.devDelegateMessagesList.AddMsg(ServerValue[1]);
                        }
                        break;
                    default:
                        break;
                }
                //JsonConvert.DeserializeObject<MessageAmanager>()

                //将文本框输入的信息附加到txtMsg中  并显示 谁,什么时间,换行,发送了什么信息 再换行
                //  txtMsg.AppendText("服务端在 " + GetCurrentTime() + " 给您发送了:\r\n" + strRecMsg + "\r\n");
            }
        }

        /// <summary>
        /// 发送字符串信息到服务端的方法
        /// </summary>
        private void ClientSendMsg(string sendMsg, byte symbol)
        {
            byte[] arrClientMsg = Encoding.UTF8.GetBytes(sendMsg);
            //实际发送的字节数组比实际输入的长度多1 用于存取标识符
            byte[] arrClientSendMsg = new byte[arrClientMsg.Length + 1];
            arrClientSendMsg[0] = symbol;  //在索引为0的位置上添加一个标识符
            Buffer.BlockCopy(arrClientMsg, 0, arrClientSendMsg, 1, arrClientMsg.Length);

            socketClient.Send(arrClientSendMsg);
            // txtMsg.AppendText("SoFlash:" + GetCurrentTime() + "\r\n" + sendMsg + "\r\n");
        }

        //向服务端发送信息
        public void XamarinSend(string Message)
        {
            ClientSendMsg(Message, 0);
        }

        //获取在线用户信息
        public void XamarinGetUserInfo()
        {
            ClientSendMsg("001001001", 5);
        }

        //发送登录信息
        public void XamarinSendUserLogin()
        {
            string MyLogin = XamarinMessageAmanager("", $"{DeviceHelp.MyUserID}@{DevHelp.DeviceHelp.MyUserName}");
            ClientSendMsg($"002002002#{MyLogin}", 4);
        }

        快捷键 Enter 发送信息
        //private void txtCMsg_KeyDown(object sender, KeyEventArgs e)
        //{   //当光标位于输入文本框上的情况下 发送信息的热键为回车键Enter 
        //    if (e.KeyCode == Keys.Enter)
        //    {
        //        //则调用客户端向服务端发送信息的方法
        //        ClientSendMsg(txtCMsg.Text, 0);
        //    }
        //}

        string filePath = null;   //文件的全路径
        string fileName = null;   //文件名称(不包含路径) 
        选择要发送的文件
        //private void XamarinSelectFile(object sender, EventArgs e)
        //{
        //    OpenFileDialog ofDialog = new OpenFileDialog();
        //    if (ofDialog.ShowDialog(this) == DialogResult.OK)
        //    {
        //        fileName = ofDialog.SafeFileName; //获取选取文件的文件名
        //        txtFileName.Text = fileName;      //将文件名显示在文本框上 
        //        filePath = ofDialog.FileName;     //获取包含文件名的全路径
        //    }
        //}

        /// <summary>
        /// 发送文件的方法
        /// </summary>
        /// <param name="fileFullPath">文件全路径(包含文件名称)</param>
        private void XamarinSendFile(string fileFullPath)
        {
            if (string.IsNullOrEmpty(fileFullPath))
            {
                // MessageBox.Show(@"请选择需要发送的文件!");
                return;
            }

            //发送文件之前 将文件名字和长度发送过去
            long fileLength = new FileInfo(fileFullPath).Length;
            string totalMsg = string.Format("{0}-{1}", fileName, fileLength);
            ClientSendMsg(totalMsg, 2);


            //发送文件
            byte[] buffer = new byte[SendBufferSize];

            using (FileStream fs = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read))
            {
                int readLength = 0;
                bool firstRead = true;
                long sentFileLength = 0;
                while ((readLength = fs.Read(buffer, 0, buffer.Length)) > 0 && sentFileLength < fileLength)
                {
                    sentFileLength += readLength;
                    //在第一次发送的字节流上加个前缀1
                    if (firstRead)
                    {
                        byte[] firstBuffer = new byte[readLength + 1];
                        firstBuffer[0] = 1; //告诉机器该发送的字节数组为文件
                        Buffer.BlockCopy(buffer, 0, firstBuffer, 1, readLength);

                        socketClient.Send(firstBuffer, 0, readLength + 1, SocketFlags.None);

                        firstRead = false;
                        continue;
                    }
                    //之后发送的均为直接读取的字节流
                    socketClient.Send(buffer, 0, readLength, SocketFlags.None);
                }
                fs.Close();
            }
            //   txtMsg.AppendText("SoFlash:" + GetCurrentTime() + "\r\n您发送了文件:" + fileName + "\r\n");
        }

        //点击文件发送按钮 发送文件
        private void btnSendFile_Click(object sender, EventArgs e)
        {
            XamarinSendFile(filePath);
        }

        /// <summary>
        /// 获取当前系统时间
        /// </summary>
        public DateTime GetCurrentTime()
        {
            DateTime currentTime = new DateTime();
            currentTime = DateTime.Now;
            return currentTime;
        }

        //关闭客户端
        private void btnExit_Click(object sender, EventArgs e)
        {
            //Application.Exit();
        }


        /// <summary>
        /// 封装发送消息
        /// </summary>
        /// <param name="SReceiveUserID"></param>
        /// <param name="SMessage"></param>
        /// <returns></returns>
        public string XamarinMessageAmanager(string SReceiveUserID, string SMessage)
        {
            MessageAmanager message = new MessageAmanager() { Message = SMessage, ReceiveUserID = SReceiveUserID, SendUserID = DeviceHelp.MyUserID };
            return JsonConvert.SerializeObject(message);
        }

    }

    /// <summary>
    ///消息管理
    /// </summary>
    public class MessageAmanager
    {
        /// <summary>
        /// 发送者ID
        /// </summary>
        public string SendUserID { get; set; }
        /// <summary>
        /// 消息
        /// </summary>
        public string Message { get; set; }
        /// <summary>
        /// 接收者ID
        /// </summary>
        public string ReceiveUserID { get; set; }

    }

NavigationClass UI 页面跳出工具类

 public static class NavigationClass
    {
        /// <summary>
        /// 创建副本
        /// </summary>
        public static INavigation Navigation { get; set; }
        /// <summary>
        /// 跳转页面
        /// </summary>
        /// <param name="obj"></param>
        public static void PushAsync(this Page obj)
        {
            Navigation.PushAsync(obj, true);
        }
        /// <summary>
        /// 关闭窗口
        /// </summary>
        /// <param name="obj"></param>
        public static void PopAsync(this Page obj)
        {
            Navigation.PopAsync(true);
        }

        public static void RemovePage(this Page obj)
        {
            Navigation.RemovePage(obj);
        }
    }

DeviceHelp 设备参数 UI委托 文件读写工具类

 public class DeviceHelp
    {

        /// <summary>
        /// 客户端唯一ID
        /// </summary>
        public static string MyUserID = Guid.NewGuid().ToString("N");
        /// <summary>
        /// 宽度
        /// </summary>
        public static double ScreenWidth { get; set; }
        /// <summary>
        /// 高度
        /// </summary>
        public static double ScreenHeight { get; set; }
        /// <summary>
        /// 密度
        /// </summary>
        public static double Density { get; set; }

        /// <summary>
        /// 上下文对象
        /// </summary>
        public static Context Context { get; set; }

        /// <summary>
        /// Sockect 实例化对象
        /// </summary>
        public static XamarinSockectClient xamarinSockectClient { get; set; }

        /// <summary>
        /// UI委托
        /// </summary>
        public static DevDelegateUpdateUi devDelegateUpdateUi { get; set; }
        /// <summary>
        /// 消息列表
        /// </summary>
        public static DevDelegateMessagesList devDelegateMessagesList { get; set; }

        /// <summary>
        /// 用户名
        /// </summary>
        public static string MyUserName { get; set; }
        /// <summary>
        /// 更新标题
        /// </summary>
        public static DevDelegateTitle devDelegateTitle { get; set; }

        //var width = Resources.DisplayMetrics.WidthPixels;

        //var height = Resources.DisplayMetrics.HeightPixels;

        //var density = Resources.DisplayMetrics.Density; //


        public void SaveImage(string filepath)
        {

            var imageData = System.IO.File.ReadAllBytes(filepath);
            var dir = Android.OS.Environment.GetExternalStoragePublicDirectory(
            Android.OS.Environment.DirectoryDcim);
            var pictures = dir.AbsolutePath;
            var filename = System.DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".jpg";
            var newFilepath = System.IO.Path.Combine(pictures, filename);

            System.IO.File.WriteAllBytes(newFilepath, imageData);
            //mediascan adds the saved image into the gallery
            var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
            mediaScanIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(newFilepath)));
            DevHelp.DeviceHelp.Context.SendBroadcast(mediaScanIntent);
        }

        /// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="filepath"></param>
        /// <param name="Data"></param>
        public static void SaveFile(string filepath, byte[] Data)
        {

            // var imageData = System.IO.File.ReadAllBytes(filepath);
            var dir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDcim);
            var pictures = dir.AbsolutePath;
            //  var filename = System.DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".jpg";
            var newFilepath = System.IO.Path.Combine(pictures, filepath);

            System.IO.File.WriteAllBytes(newFilepath, Data);
            //mediascan adds the saved image into the gallery
            var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
            mediaScanIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(newFilepath)));
            DevHelp.DeviceHelp.Context.SendBroadcast(mediaScanIntent);
        }


        /// <summary>
        /// 读取指定文件
        /// </summary>
        /// <param name="filepath"></param>
        /// <returns></returns>
        public static byte[] ReadFile(string filepath)
        {
            try
            {
                var Data = System.IO.File.ReadAllBytes(filepath);
                return Data;
            }
            catch (Exception ex)
            {
                return null;
            }

        }
    }
  
    public class DevDelegateUpdateUi
    {
        public delegate void InitUi(string message);
        public InitUi InitUI;
    }

    public class DevDelegateMessagesList
    {
        public delegate void InitUi(string message);
        public InitUi AddMsg;
    }

    public class DevDelegateTitle
    {
        public delegate void UpdateTitle(string Title);
        public UpdateTitle updateTitle;
    }

DialogsListControlRenderer 在线列表数据更新实现

IOnDialogClickListener 列表单击事件接口

必须注册: dialogsListAdapter.OnDialogClickListener = this;

    public class DialogsListControlRenderer : ViewRenderer<DialogsListControl, LinearLayout>, IOnDialogClickListener
    {
   public DialogsListControlRenderer(Context context) : base(context)
        {

        }

        private Com.Stfalcon.Chatkit.Dialogs.DialogsList dialogsList;

        private LinearLayout linearLayout;

        private Com.Stfalcon.Chatkit.Dialogs.DialogsListAdapter dialogsListAdapter;
        protected override void OnElementChanged(ElementChangedEventArgs<DialogsListControl> e)
        {
        
            DevDelegateUpdateUi devDelegateUpdateUi = new DevDelegateUpdateUi();
            devDelegateUpdateUi.InitUI += new DevDelegateUpdateUi.InitUi(AddItem);
            DeviceHelp.devDelegateUpdateUi = devDelegateUpdateUi;
            var x = Inflate(Context, Resource.Layout.DialogsListLayout, null);
            x.Click += DialogsListView_Click;
           

            if (linearLayout == null)
            {
                linearLayout = x as LinearLayout;
            }

            if (dialogsList == null)
            {
                var dialogsListView = linearLayout.FindViewById<Com.Stfalcon.Chatkit.Dialogs.DialogsList>(Resource.Id.dialogsList1);
               
                dialogsList = dialogsListView;
            }

            dialogsList.Click += DialogsListView_Click;

            dialogsList.LongClick += DialogsListView_Click;


            dialogsListAdapter = new Com.Stfalcon.Chatkit.Dialogs.DialogsListAdapter(new SampleImageLoader(Context));

            dialogsList.SetAdapter(dialogsListAdapter); 
            DevHelp.DeviceHelp.xamarinSockectClient.XamarinGetUserInfo();
            //JsonConvert.DeserializeObject<MessageAmanager>()

            linearLayout.Click += DialogsListView_Click;
          
            dialogsListAdapter.OnDialogClickListener = this;
            SetNativeControl(linearLayout);
        }

        public void AddItem(string message)
        {
            Device.BeginInvokeOnMainThread(() =>
            {
                string[] strUser = message.Split("#");
                dialogsListAdapter.Clear();
                foreach (var item in strUser)
                {
                    var itValue = item.Split('@');
                    SampleUser sample1 = new SampleUser();
                    sample1.Avatar = itValue[1];
                    sample1.Id = itValue[0];
                    sample1.Name = itValue[1];
                    SampleMessage message1 = new SampleMessage {Id= itValue[0],Text="您有新的消息!!!", User= sample1 };
                    SampleDialog sample = new SampleDialog(sample1, message1) { Id= itValue[0] ,DialogName= itValue[1] };
                    dialogsListAdapter.AddItem(sample);
                }            
          
            });
        }


       ///列表单击事件
        public void OnDialogClick(Java.Lang.Object p0)
        {
            MessagesListPage messagesListPage = new MessagesListPage();
            UserInfoHelp.SampleDialog = p0 as SampleDialog;
            messagesListPage.PushAsync();
        }
       ///列表长按事件
        public void OnDialogLongClick(Java.Lang.Object p0)
        {

        }
    }

MessagesListControlRenderer 消息动态更新实现

IOnMessageClickListener 消息单击事件接口

IOnMessageLongClickListener 消息长按事件接口

接口注册不然不会触发 messagesListAdapter.SetOnMessageClickListener(this);
messagesListAdapter.SetOnMessageLongClickListener(this);

//好友聊天页面标题 方法注册
DeviceHelp.devDelegateTitle.updateTitle(UserInfoHelp.SampleDialog.DialogName);

//好友消息动态更新方法注册
DevDelegateMessagesList devDelegateMessages = new DevDelegateMessagesList();
devDelegateMessages.AddMsg += new DevDelegateMessagesList.InitUi(AddFendMsg);
DeviceHelp.devDelegateMessagesList = devDelegateMessages;

 public class MessagesListControlRenderer : ViewRenderer<MessagesListControl, LinearLayout>, IOnMessageClickListener, IOnMessageLongClickListener
    {
        public MessagesListControlRenderer(Context context) : base(context)
        {
            DevHelp.DeviceHelp.Context = context;
        }

        private LinearLayout linearLayout;

        private Com.Stfalcon.Chatkit.Messages.MessagesList messagesList;

        private Com.Stfalcon.Chatkit.Messages.MessagesListAdapter messagesListAdapter;
        protected override void OnElementChanged(ElementChangedEventArgs<MessagesListControl> e)
        {
            var x = Inflate(Context, Resource.Layout.MessagesListLayout, null);
            //    MessagesListControl messagesListControl= e.NewElement;
            //    messagesListControl.AddMsg += AddMsg;

            MessageManager message = new MessageManager();
            message.AddMsg += AddMsg;
            MessageHelpObj.messageManager = message;

            DevDelegateMessagesList devDelegateMessages = new DevDelegateMessagesList();
            devDelegateMessages.AddMsg += new DevDelegateMessagesList.InitUi(AddFendMsg);
            DeviceHelp.devDelegateMessagesList = devDelegateMessages;

            if (linearLayout == null)
            {
                linearLayout = x as LinearLayout;
            }

            if (messagesList == null)
            {
                var messagesListView = linearLayout.FindViewById<Com.Stfalcon.Chatkit.Messages.MessagesList>(Resource.Id.messagesList);
                messagesList = messagesListView;
            }
            //Guid.NewGuid().ToString()


            messagesListAdapter = new Com.Stfalcon.Chatkit.Messages.MessagesListAdapter(DeviceHelp.MyUserID, new SampleImageLoader(Context));

            messagesList.SetAdapter(messagesListAdapter);         

            messagesListAdapter.SetOnMessageClickListener(this);
            messagesListAdapter.SetOnMessageLongClickListener(this);


            SetNativeControl(linearLayout);
            
            DeviceHelp.devDelegateTitle.updateTitle(UserInfoHelp.SampleDialog.DialogName);
        }

        //public string guid = Guid.NewGuid().ToString();

        public string xAvatar = "xiaoming";
        public string xName = "张三";
        /// <summary>
        /// 增加消息
        /// </summary>
        /// <param name="message"></param>
        public void AddMsg(SampleMessageControl message)
        {
            SampleMessage sample = new SampleMessage { Text = message.Text, Id = DeviceHelp.MyUserID };
            sample.User = new SampleUser() { Id = DeviceHelp.MyUserID, Avatar = xAvatar, Name = xName };

            messagesListAdapter.AddToStart(sample, true);
        }
        /// <summary>
        /// 增加消息
        /// </summary>
        /// <param name="message"></param>
        public void AddFendMsg(string message)
        {
            Device.BeginInvokeOnMainThread(() =>
            {
                MessageBox box = JsonConvert.DeserializeObject<MessageBox>(message);

                SampleMessage sample = new SampleMessage { Text = box.Message, Id = box.SendID };
                sample.User = new SampleUser() { Id = box.SendID, Avatar = box.Name, Name = box.Name };

                messagesListAdapter.AddToStart(sample, true);
            });
        }

        public void OnMessageClick(Java.Lang.Object p0)
        {

        }

        public void OnMessageLongClick(Java.Lang.Object p0)
        {
            p0.NotifyAll();
        }

    }

    public class MessageBox
    {
        /// <summary>
        /// 接收人
        /// </summary>
        public string RID { get; set; }

        public string Message { get; set; }

        public string Name { get; set; }
        /// <summary>
        /// 发送人
        /// </summary>
        public string SendID { get; set; }
    }

MessageInputControlRenderer 发送消息实现

IInputListener 消息提交 接口

//OnSubmit 发送信息
接口注册 messageInput.SetInputListener(this);
// 发送消息到服务器方法实现
DevHelp.DeviceHelp.xamarinSockectClient.XamarinSend(Message);

public class MessageInputControlRenderer : ViewRenderer<MessageInputControl, LinearLayout>, IInputListener
   {
       public MessageInputControlRenderer(Context context) : base(context)
       {

       }

       private Com.Stfalcon.Chatkit.Messages.MessageInput messageInput;

       private LinearLayout linearLayout;

       protected override void OnElementChanged(ElementChangedEventArgs<MessageInputControl> e)
       {
           var x = Inflate(Context, Resource.Layout.MessageInputLayout, null);
    
       
           if (linearLayout == null)
           {
               linearLayout = x as LinearLayout;
           }

           if (messageInput == null)
           {
               var messageInputView = linearLayout.FindViewById<Com.Stfalcon.Chatkit.Messages.MessageInput>(Resource.Id.theMessageInput);
               messageInput = messageInputView;
           }
           messageInput.SetInputListener(this);
           SetNativeControl(linearLayout);
       }

     

       public bool OnSubmit(ICharSequence p0)
       {
           var msg = p0.ToString();
           SampleMessageControl sample = new SampleMessageControl { Text = msg };
           MessageHelpObj.messageManager.AddMsg(sample);
           MessageBox box = new MessageBox { RID = UserInfoHelp.SampleDialog.Id, SendID = DevHelp.DeviceHelp.MyUserID, Message = p0.ToString(), Name = DevHelp.DeviceHelp.MyUserName };
           var Sedmsg = JsonConvert.SerializeObject(box);
           string Message = "000200030006#"+ Sedmsg;
           DevHelp.DeviceHelp.xamarinSockectClient.XamarinSend(Message);


           return true; 
       }
   }

##获取设备宽度,高度 屏幕 密度
代码实现:

 
            var width = Resources.DisplayMetrics.WidthPixels; //高度

            var height = Resources.DisplayMetrics.HeightPixels;//宽度

            var density = Resources.DisplayMetrics.Density; //屏幕密度



            DeviceHelp.ScreenWidth = width / density; //屏幕宽度

            DeviceHelp.ScreenHeight = height / density; //屏幕高度 含24个单位的标题栏高度 通过OnSizeAllocated获取的高度不含标题栏高度

            DeviceHelp.Density = density;

以上是代码实现:
下面展示实际效果:

请添加图片描述
好友列表

请添加图片描述
好友Caozhen001 与好友Caozhen002 对话实现

请添加图片描述
好友Caozhen002与好友Caozhen001 对话实现

这里是客户端的实现 下期介绍 服务端的实现

本期就到这里 谢谢大家,不足之处请指点一二;

需要源码请假博主微信

请添加图片描述

相关说明: ConsoleApplication1_sERVER ----PC-服务端 MyNetTest --------------------IOS-客户端 1、PC-服务端 只是一个运行在windows系统下的 控制台程序。接收来自客户端的信息。 2、IOS-客户端 运行在ios模拟器上,连接PC服务端的ip,发生相关信息。 3、两台主机,一台是运行windows系统的计算机。另外一台是MacBook计算机。运行ios模拟器。 4、pc-服务端,可以用vs2008打开并且编辑。 5、ios客户端,使用的是XamarinStudio 打开并且编辑。 以下是这个例子中的特别提到的地方 A、这个例子是完全用C#写的。 B、ios由于是伪后台,当程序退回到后台,系统留给程序的可运行时间就只有3分钟。 过了3分钟,就会把这个程序的所有线程挂起(当然内部预留了长任务运行这一后招)。 经过多次试验后,可以借助着3分钟的长任务运行,然后通过简单的修改来突破这个界限。 在本例子中,所有线程共享一个线程ID。 其中只需要一条线程负责不停的延长这个线程ID的运行时间,然后其他的线程就只需要专注于其本应该要做的任务即可。 C、本例子中,还实现了另外一个功能,就是ios程序与PC程序进行socket。当然是最为简单的。 ---------------- 由于本人也是刚刚使用c#开发ios程序,初入门,为了这两个问题,也是研究了很久,可查的资料又很少。 希望能够帮助到同样遇到困难的你。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值