2017年12月25日 星期一

for xamarin ios,javascript call back to UIView

有些程式在web已經寫好了,想要xamarin UI中應用的話,
就ios而言,就可以利用"WebKit"了
今天就先討論從javascript丟回來呼叫xamarin UI怎麼做
==============某個要查看網頁的viewcontroller======
    public partial class MyMapViewController : UIViewController, IWKScriptMessageHandler {
        public MyMapViewController () : base("MyMapViewController ", null) {
        }

        public override void DidReceiveMemoryWarning() {
            base.DidReceiveMemoryWarning();
         
            // Release any cached data, images, etc that aren't in use.
        }

        public override void ViewDidLoad() {
            base.ViewDidLoad();

            var userController = new WKUserContentController();
            userController.AddScriptMessageHandler(this, "myApp");
            var config = new WKWebViewConfiguration {
                UserContentController = userController
            };
            var webkitView= new WebKit.WKWebView(viewContainScroll.Frame, config);
            webkitView.LoadRequest(new Foundation.NSUrlRequest(new NSUrl("你的web網址")));
            webkitView.ContentMode = UIViewContentMode.ScaleToFill;
            this.View.AddSubview(webkitView);
       }

public void DidReceiveScriptMessage(WKUserContentController userContentController,           WKScriptMessage message) {
            var msg = message.Body.ToString();
            System.Diagnostics.Debug.WriteLine(msg);
        }

============================================
手機端好了,再來就是看遙遠的雲端了
===============================
 <html>
   <body>
    <script type="text/javascript">
       //找個按鈕觸發這個doCallBack吧
       var doCallBack = function ( paraStr) {
            //以下的動作就會呼叫包含他的webkitview所AddScriptMessageHandler的物件的     
            //「DidReceiveScriptMessage」的函數來接受訊息了
            window.webkit.messageHandlers.myApp.postMessage("param=" + paraStr);
        }
         ...
         ...
         .....
    </script>
   </body>
</html>
================================
完整的討論來源,請參考這裡
現在的前端的工程師不只是二刀流的,
通常是剪刀菜刀剃頭刀手術刀小李飛刀都要會了

2017年12月22日 星期五

繪製半透明的png於底圖上之

正如同「身為一個汽車維修員,有個錘子在身邊,也很合邏輯」一樣
工程師嘛,圖片加工也要會是很自然不過的事了,特別是你有用到平面圖的機制時
「I am here」標示本來是不需要半透明的,基於方便參考其他地標時,還是給個半透明的版本好了
===================================================
               ...
               ...
              ...
              var Alpha=0.55f;
                Bitmap bmpIamHere = new Bitmap(imgIamHereIcon);
                Color background = bmpIamHere.GetPixel(0, 0);
                 //設定透明色為.....
                bmpIamHere.MakeTransparent(background);
                Graphics gfxMap = Graphics.FromImage(imgMap);
                //set alpha value.
                ColorMatrix cm = new ColorMatrix();
                cm.Matrix33 = Alpha;
                ImageAttributes ia = new ImageAttributes();
                ia.SetColorMatrix(cm);
             
                //沒有 Alpha值時,直接繪製,gfxMap.DrawImage(bmpIamHere, (float)markAtX, (float)markAtY, bmpIamHere.Width, bmpIamHere.Height);
               //有alpha值時,請用以下方式
                gfxMap.DrawImage(bmpIamHere, new Rectangle((int)markAtX, (int)markAtY, bmpIamHere.Width, bmpIamHere.Height), 0, 0, bmpIamHere.Width, bmpIamHere.Height, GraphicsUnit.Pixel, ia);
                ...
               ...
               ...
=================================================
來源在此

加油了

2017年12月20日 星期三

ERROR ITMS-90502: "Invalid Bundle. Apps that only contain the arm64 slice must also have 'arm64' in the list of UIRequiredDeviceCapabilities in Info.plist."

在用 application Launcher 上傳ipa到 iTunes connect  時
遇到以下的狀況:
「ERROR ITMS-90502: "Invalid Bundle. Apps that only contain the arm64 slice must also have 'arm64' in the list of UIRequiredDeviceCapabilities in Info.plist."」
這樣的問題直接就是去Info.plist去改:
==============================
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
===============================
(從原來的armv7改成arm64就可以了)
記得:就算是只做testflight,也要把media.xcassets中的 icon都指定完才可以上beta測試
還有,用application launcher上傳完ipa檔後,不要只是在  iTunes connect的web介面去看「activities/活動」看它有沒有上傳
有時.......是不會出現的, iTunes connect會把問題寄到你的email而不是在application launcher上傳驗證後就直接給你答案.
多注意點不同的資訊管道吧

2017年12月10日 星期日

for xamarin android :如何自行觸發FCM中 service「onTokenRefresh」事件

相信大家都已經會基本的FCM的推播架構了
不過,或許你會問「如何觸發FirebaseInstanceIdService 中的OnTokenRefresh事件」
 官方的回應是安裝,反安裝套件,或是過一段時間會重行配置token
有個不錯的觸發方式可以參考
=======在某個activity中=================
 ...
...
... 按鈕click事件

btnDeleteToken.Click +=  delegate (object sender, EventArgs e) {
                 //注意,deleteFcmInstanace一定要另起執行緒執行,不能在MAIN_THREAD中執行
                var th = new System.Threading.Thread(
                      () => {
                          deleteFcmInstanace();
                      }
                 );
                th.Start();
            };
...
...
...
void deleteFcmInstanace(){
                Firebase.Iid.FirebaseInstanceId.Instance.DeleteInstanceId();
                Log.Debug("DONE", "delete token works");
               //一定要再InitializeApp,否則取得的token是null的
              //以下動作執行後,就會觸發FirebaseInstanceIdService 中的OnTokenRefresh事件
                Firebase.FirebaseApp.InitializeApp(this);
 var refreshedToken = Firebase.Iid.FirebaseInstanceId.Instance.Token;
}

====================================
做這事是有點不實際,只是想要驗證一下罷了,大家應該用不到
不過「好奇心」是所有programmer應該有的吧



2017年11月28日 星期二

怎麼改,MonoAndroid,Version 都是錯的!?


在升級android一些套件時(尤其是FCM需要的googplayservice.base)會遇到以下的相關套件狀況
=============================
無法安裝封裝 'Xamarin.Android.Support.Compat 24.2.1'。您正嘗試將此封裝安裝到以 'MonoAndroid,Version=v5.0' 為目標的專案,但該封裝不包含任何與架構相容的組件參考或內容檔。如需詳細資訊,請連絡封裝作者。

==============================
這時,除了參考:
http://neo-tech-tw.blogspot.tw/2017/08/vs2015xamarinupdate.html
到xamarin總站去下載xamarin.android setup安裝之外
還要去vs的android  的SDK manager下載比較高級的SDK版本(7.11...當然愈齊全愈好)

最重要的是要去這個android的project properties設定target frameowork到「Android 7.1(Nougat)」

存檔,然後,離開,再重新進入vs
記得,只改專案的屬性檔存檔就去Nuget做udpate還是會有最初MonoAndroid version的錯誤,
只有重新進入vs才有用

2017年11月27日 星期一

無法載入組件..... ICSharpCode.SharpZipLib, Version=0.86.0.518

Could not load file or assembly CSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73'  ......

寫的這麼落落長,好像很多人也遇到這問題,
有的解法是去改"<SpecificVersion>False</SpecificVersion>"
(ref: https://github.com/icsharpcode/SharpDevelop/issues/605 )

有的是去改token 
ref: http://www.cnblogs.com/zinan/p/5075903.html

有的是請你去參考那裡改抓dll存在package中的路徑

而我,最後是用這招 :到「工具」->「NuGet封裝管理員」-->「套件管理器主控台」
那裡下指令「Install-Package ICSharpCode.SharpZipLib -Version 0.86.0.518」
就解決這個很麻煩的問題了

參考這裡

(如果是開發web 應用程式的話,不能只update bin資料夾,還要記得把在web.config相關組件的訊息一併update到正式站台去,否則還是錯的)

大家加油了

2017年10月24日 星期二

mvc4->mvc5發生這樣的錯誤「[A]System.Web.WebPages.Razor.Configuration.HostSection 無法轉型為 [B]System.Web.WebPages.Razor.Configuration.HostSection.」

======升級MVC4 to MVC5時,發生了Razor版本的問題=====

[A]System.Web.WebPages.Razor.Configuration.HostSection 無法轉型為 f[B]System.Web.WebPages.Razor.Configuration.HostSection. 類型 A 源自 'System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' (在內容 'Default' 中,位置為 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Web.WebPages.Razor\v4.0_2.0.0.0__31bf3856ad364e35\System.Web.WebPages.Razor.dll'). 類型 B 源自 'System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' (在內容 'Default' 中,位置為 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\.....\183bffad\c40c5844\assembly\dl3\ea4310d4\00dbbd75_6c3ad001\System.Web.WebPages.Razor.dll').

=============================================
這時,請到View之下的web.config.
找出<section name="host" type ....>
及<section name="pages" type=....>
兩個節點中的「Razor, Version=2.0.0....」改為「Razor,  Version=3.0.....」
如下圖:

以上,大家加油了

2017年10月21日 星期六

for Extj4 grid 讓某欄允許多行文字折行顯示

extjs5 是在column中設定「 cellWrap: true」就可以了
但是在Extjs4呢?
需要在css中設定一下了,基本上不出white-space:normal 這個設定,
參考http://jaspreetchahal.org/extjs-grid-multi-line-rows/

但如果你要直接寫在某欄位的話
就直接寫在randerer吧,
別忘了加入「important」這個複寫指令
如:
==========果然important不是叫假的=========
renderer: function (value, metaData, record, rowIndex, colIndex, store, view) {
                                return '<div style="white-space:normal !important;">' + value + '</div>';
                            },
==================================

以上,大家加油了

2017年9月30日 星期六

如何在你的windows中輸出Base64 X509憑證

參考影音:
https://www.youtube.com/watch?v=PXopk5RbDbc
但是在「匯出私密金鑰」時,選「否,不要匯出私密金鑰」之後那頁就有Base64 X509格式了
win. 8.1在cmmand.com輸出mcc.exe時不會出現mmc,會出現hyperV 管理員
這時要用系統管理員的權限啟動command.com再輸入mmc就會出現了

2017年8月19日 星期六

for xamarin 如何繪製一二維條碼

二維的比較簡單,先講二維的好了
不用ZXing,直接用CG--CoreGraphic套件就可以了
============================================
            /*
            Correction level option as below:
            L, // Level L (Low) 7% of codewords can be restored.
    M, // Level M (Medium) 15% of codewords can be restored.
           Q, // Level Q (Quartile) 25% of codewords can be restored.
            H // Level H (High) 30% of codewords can be restored.          
             */
            CoreImage.CIQRCodeGenerator ciQrCodeGen = new CoreImage.CIQRCodeGenerator() {
                Message = NSData.FromString("這裡面可以裝下1700多個漢字,請好好發揮了"),
                CorrectionLevel = "L",
            };
            var context = CoreImage.CIContext.FromOptions(null);
            //假設有個UIImageView叫imgQrCode,放置二維條碼
            imgQrCode.Image=UIImage.FromImage(
                context.CreateCGImage(ciQrCodeGen.OutputImage,ciQrCodeGen.OutputImage.Extent)
            );
============================================

相形之下,一維比較麻煩(以39碼為例):
---------------------------step1:-------------------------------------------------------
public interface IBarcodeService {
        Stream ConvertImageStream(string text, int width = 300, int height = 130);
    }
---------------------------step2:-------------------------------------------------------
class BarcodeService : IBarcodeService {
        public Stream ConvertImageStream(string text, int width = 300, int height = 130) {
            var barcodeWriter = new ZXing.Mobile.BarcodeWriter {
                Format = ZXing.BarcodeFormat.CODE_39,
                Options = new ZXing.Common.EncodingOptions {
                    Width = width,
                    Height = height,
                    Margin = 10
                }
            };
            barcodeWriter.Renderer = new ZXing.Mobile.BitmapRenderer();
            var bitmap = barcodeWriter.Write(text);
            var stream = bitmap.AsPNG().AsStream(); // this is the difference
            stream.Position = 0;

            return stream;
        }
---------------------------step3:-------------------------------------------------------
//假設我們要把一維條碼繪在UIImageView "imgCode39"上面...
var stream =new  Barcode.BarcodeService().ConvertImageStream("10607UP197419461A5B");
 imgCode39.Image= UIImage.LoadFromData(Foundation.NSData.FromStream(stream));


參考:https://forums.xamarin.com/discussion/28161/barcode-rendering-with-zxing-net-in-my-xamarin-forms-app

 大家加油了

2017年8月17日 星期四

vs2015一直說有xamarin更新,卻沒辦法update到新的版本去,如何是好

最近在用vs2015 開發mobile專案時,IDE一直說有update,也下載了,可是一直在等候安裝

(按了「安裝」也沒用,看的到吃不到令人很幹)

這時,請到:https://store.xamarin.com/account/my/subscription/downloads
登入你的xamarin account
不要點頁面中藍色的「Download Xamarin 」,是要到之下的那幾個button去各別選Xamarin.IOS & Xamarin.Android去安裝


給不想升級到vs2017的朋友參考

同場加映,
1「xamarin profiler 1.5.5」google一下就有了,在
https://developer.xamarin.com/releases/profiler/profiler-1.5/profiler-1.5.5/

2.ios simulator在
https://developer.xamarin.com/guides/cross-platform/windows/ios-simulator/
文中段「Download the installer and install on your Windows computer. Visual Studio Enterprise with Xamarin should already be installed.」那個 installer連結就有了



2017年7月29日 星期六

for xamarin ios ,用Nib.Instantiate(null, null)[0]時,出現「 System.InvalidCastException: Specified cast is not valid. 」錯誤訊息

如果只是設計一般iphone用的custorm UIView,你應該不會用到xcode去改view的大小,了不起用ipad的view去做scrollview的subview
可是如果用ipad要去做更大,超過landscape寬度的view,那你不只是在 simulated matrix的size設定為「freeform 」之外,你還要去xcode改他的寬度才可以(當然日後這個view也是要放在scrollview中才能捲動的)
有時我們會用temp.xib去xcode做這些上述動作,再回來把temp.xib的內容copy past到我們正式要用的xib檔中,可是在用xib檔產用view時,卻出現了「 System.InvalidCastException」訊息
=====在那個UIView .cs中.....=======================
....
....
...
 [Register("UIMyViewClass ")]
    public class UIMyViewClass : UIView {
     ....
    .....
    public static UIMyViewClass CreateMyView() {
            return (UIMyViewClass )Nib.Instantiate(null, null)[0];
     }
}
=======================================
在上述發生「 System.InvalidCastException: Specified cast is not valid. 」錯誤訊息
真害,明明以前都很正常的啊...
嗯,問題就出在xib檔中,
========================================
...
....
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="UIMyViewClass "/>
        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
        <view contentMode="scaleToFill" id="1" customClass="UIMyViewClass ">
...
....
========================================
就是要對一下「customClass」有沒有錯,這是這麼簡單罷了



2017年6月27日 星期二

Xamarin IOS:label中的Attributed Text怎麼用啊?

剛開始做xamarin畫面設計時真的是抱怨連連,尤其是習慣了html的人
雄雄想要在文字標籤中加個底線,卻一直不知如何著手.
label物件中有個文字屬性叫AttributedText,就可以派上用場了
(事實上你在GUI builder中找label的"text"屬性欄位,就Plain & Attribute,但是你選了「Attributed」會出現「not support in this version」.....沒錯啦,在xcode設計工具中是有的選)
回到問題,要做個堂堂正正的...不,要做有個底線的文字標籤,就參考以下的做法:
----------------------------------------
myLabel.AttributedText = new NSAttributedString(
                "別踩了我的底線",
                underlineStyle: NSUnderlineStyle.Single);
----------------------------------------

事實上這個機制,還可以套用更複雜的html語法
==================================
var attr = new NSAttributedStringDocumentAttributes();
            var nsError = new NSError();
            attr.DocumentType = NSDocumentType.HTML;

            var myHtmlText = "<u>I服了 You</u>";
            var myHtmlData = NSData.FromString(myHtmlText, NSStringEncoding.Unicode);
            myLable.AttributedText = new NSAttributedString(myHtmlData, attr, ref nsError);
==========================
來源參考:
1.https://forums.xamarin.com/discussion/23670/how-to-display-html-formatted-text-in-a-uilabel
2.https://stackoverflow.com/questions/15643232/underline-text-in-uilabel-in-monotouch-porting-objc-code
3.https://www.youtube.com/watch?v=5-ZnV3jQd9I

以上,加油了!!

2017年6月12日 星期一

for Xamarin IOS : 為什麼「 NSData.FromString(uri)」總是傳回空(null)值!?

公司已經把觸手從賣場伸向行動設備了
原本在pos上的資源可以用http下載的方式跟手機平台契合
在做商品查詢中一定會用到圖片下載
明明在公司內部網路就正常,
可是一旦用internet時,「var data=NSData.FromString(uri)」就會傳回空值,連帶接下來的「UIImage.LoadFromData(data);」它就死掉了
Google一下,原來這個URL是要用https才行,
蘋果真的是太龜毛了可是我就是要用非https的網路資源啊也不是無可救藥啦只要在info.plist最後加上這個設定
==========================
<key>NSAppTransportSecurity</key>
 <dict>
    <key>NSAllowsArbitraryLoads</key> 
   <true/>  
</dict>
 ================================
就可以了來源在這裡
大家一起加油吧

2017年6月5日 星期一

for Extjs4 ,如何正確使用Ext.TaskManager.start & Ext.TaskManager.stop

範例如下:
===================================
var config = {


    msg: 'Display Time',
    modal: true,
    buttons: Ext.Msg.OKCANCEL,
    fn: displayTime
}

Ext.MessageBox.msgButtons[0].setText('Start');
Ext.MessageBox.msgButtons[3].setText('Stop');

Ext.MessageBox.show(config);

function start_task() {
   Ext.MessageBox.updateText('????:' + Ext.util.Format.date(new Date(), 'Y-m-d g:1:s A'));
}

var task = { // moved outside function so it was not called over and over
    run: start_task,
    scope: this,
    interval: 1000
}

function displayTime(id) {
 
    if (id == 'ok') {
       // task was here ... was not always defined due to if statement; was also recalled each time
       Ext.TaskManager.start(task);
    } else {
        Ext.MessageBox.updateText('Paused!');
        Ext.TaskManager.stop(task);
    }
};
============I tried,it works===========================
來源網址在此
大家一起加油吧

2017年3月29日 星期三

for xamarin ios,在UI builder/Deigner 對最底層的viewc設定好透明度為半透明時,上面的view也跟著變成了半透明了,如何是好?

相信用xamarin開發使用者界面時,大家多少都會用到設計modal view的時候
今天不討論如何做modal view(有興趣的朋友自己去查「ModalPresentationStyle」&「PresentViewController」等相關指令)
而是會遇到一個問題:如果只是單純把那個modal ViewController的view的background color設定為「clear」的話,那顯示出我們設計的modalview時,會跟母畫面沒有區隔(如果你有為這modal view加些陰影就比較好一點)

那如果做到跟UIAlertView一樣在對話框的外圍做出半透明?
這時候你會想直接在那個Modal ViewController的底色選灰色,然後設定alpha值,是吧,
怪事就發生了,連帶上面的這個淺青色的view也變成半透明的,像這樣....
(這張我是在對話框那裡加再加了一層下去,看仔細點,母視窗UITable Cell的線快看到,如果項目很多個的話,字就會出現在淺藍對話框上面,真的是好可怕的靈異現象啊)

就這樣滿足了?還是要放棄了?
放心啦,這真的是要coding才能解決的,不要老是認為View Designer就一切幫你做好了,
有些人也是有遇到這狀況,答案是不要在UI builder中打轉、加幾個圖層,而是一行指令
(當然你的最底層view的背景色還是要設定為clear,透明度設回去為「1」)
===================就是這句===================================
View.BackgroundColor = UIColor.Black.ColorWithAlpha( new System.nfloat( 0.4));
==========================================================
結果如下圖:

這樣,就是我們要的如同UIAlertView那樣有底色又modal的對話框了
更多細節,
請參考這裡




2017年3月3日 星期五

for Extjs4,如何在tab 頁籤切換前先做確認動作

如果是直接想法是在beforetabchange事件中等 Ext.Msg.confirm傳回true/false
問題是 Ext.Msg.confirm是非同步的,也就是在出現 Ext.Msg.confirm頁籤就已經切換了
如何是好?
有個變通的方式--先在beforetabchange中傳回false,等 Ext.Msg.confirm再手動切換activeTab
參考以下片段
===============================
 beforetabchange: function (tabPanel, newCard, oldCard, eOpts) {
//...如果沒異動,直接return true...
//需確認
Ext.Msg.confirm("modified ", 'Content modified but not saved yet<br>Are you sure to exit current tab?',
                                                             function (answer) {
                                                                 if (answer == 'yes') {
                                                                     tabPanel.suspendEvents();//為什麼要做suspendEvent?因為以下的setActiveTab又會觸發beforetabechange事件,
                                                                     tabPanel.setActiveTab(newCard);//手動切換tab
                                                                     tabPanel.resumeEvents();//恢復事件傾聽
                                                                 } else {
                                                                 }
                                                             });
  //always return false,since we will active tab by confirmation.
    return false;
=========================================
來源,參考這裡
加油了,

2017年2月18日 星期六

for Extjs4 numberfield的事件控制之一二事

numberfield好用在於有提供格式、最大最小值,以及spinner做微調加減之用
不過事件控制上有一點小小的問題
如果只用keyup/keydown event listener的話,是無法收到spinner被click的事件
但如果用了"change" event listener的話,那麼會在form.setValues(只要是對這欄位設定值時)
就會觸發change事件,如何是好?
 既然問題是出在事件,那就把事件擱置處理吧
example:
-------假設nubmerFieldWithSpinner的listeners 有change事件--
        var form = me.down('form').getForm();
        var  nubmerFieldWithSpinner = form.findField('.....');
        nubmerFieldWithSpinner .suspendEvents();
        form.setValues(......);
        nubmerFieldWithSpinner .resumeEvents(false);
----------------------------------------------------------------------------
參考出處在此
加油了,