I am using WebView for loading websites in my project. It is loading websites but very slow. It takes around 10 to 15 seconds to load this site.
I try a solution from this thread. I have added android:hardwareAccelerated="true" on the manifest under application level, but no luck.
For iOS and Windows the solution is below: But I don't know how to create the custom render.
In iOS, try to use WKWebView instead of UIWebView.
For the UWP, use Windows.UI.Xaml.Controls.WebViewcontrol instead of using the built-in Xamarin WebView control.
Can I get the sample custom renderer for iOS and Windows-like above?
It is loading websites but very slow
The speed of loading website will up to lots of causes . For example, it will consume a lot of time if the web contains many remote css/js file . And it will also up to network performance .
The link that you provided loads slow even if on browser on my side . It contains lots of remote css if we check the source code.
For Android , We can create an custom renderer webview to accelerate it.
Set Render Priority to hight.
Enable the dom storeage.
When Loading the html, we can disable the image showing, when
loading finished, load the image by
Control.Settings.BlockNetworkImage.
Enable the Cache, if you load it at the nexttime, you can load it
quickly.
[assembly: ExportRenderer(typeof(Xamarin.Forms.WebView), typeof(MyWebviewRender))]
namespace MyWebviewDemo.Droid
{
public class MyWebviewRender : WebViewRenderer
{
public MyWebviewRender(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
base.OnElementChanged(e);
Control.Settings.JavaScriptEnabled = true;
Control.Settings.SetAppCacheEnabled(true);
Control.Settings.CacheMode = Android.Webkit.CacheModes.Normal;
Control.Settings.SetRenderPriority(RenderPriority.High);
Control.Settings.DomStorageEnabled = true;
Control.Settings.BlockNetworkImage = true;
Control.SetWebChromeClient(new MyWebChromeClient());
}
}
internal class MyWebChromeClient : WebChromeClient
{
public override void OnProgressChanged(Android.Webkit.WebView view, int newProgress)
{
base.OnProgressChanged(view, newProgress);
if (newProgress == 100)
{
// webview load success
// // loadDialog.dismiss();
view.Settings.BlockNetworkImage=false;
}
else
{
// webview loading
// loadDialog.show();
}
}
}
}
In iOS, try to use WKWebView instead of UIWebView. For the UWP, use Windows.UI.Xaml.Controls.WebViewcontrol instead of using the built-in Xamarin WebView control.
In your case it will only have less improve even if using above solution . You could add an ActivityIndicator during the loading . If you can access the website , it would be better to download the css file to local and loading them in ContentPage .
I've run across an issue using Caliburn.Micro when sharing a Screen between multiple parent Screens. In this example I have 2 tabs inside a shell. Each tab shares a single instance of SharedViewModel (essentially a singleton).
var shared = new SharedViewModel();
Items.AddRange(new []
{
new TabViewModel { Shared = shared },
new TabViewModel { Shared = shared },
});
And each tab's view has a ContentControl bound to the Shared property which is SharedViewModel:
<ContentControl cal:View.Model="{Binding Shared}"/>
Here's the order of events:
Start the app. See the shared view.
Switch to second tab. See the shared view.
Switch back to first tab. Shared view is gone.
Switch to second tab again. The shared view is there.
Proceed to pull hair out.
You can see the example application on my github.
The Screen class is based on ViewAware which caches and reuses its view once it has been loaded. As one and the same instance of a visual can't be attached to the visual tree multiple times, this leads to the behavior you're observing.
Try overriding this in your screen:
public override object GetView(object context = null)
{
return null;
}
In my AIR application in Flex 4, I use mx:HTML, and when I navigate to a location like this
html.location = 'http://www.somesite.com';
But, some websites have "alert" function in javascript like this :
alert('hello world!');
and AIR show the message in a box...
I just want to remove, or ignore these messages, but I don't know how...
I think the solution is to extend the HTMLLoader class, but my experience in Flex is too poor..
Someone can help me ?
Thank in advance :)
This is the best thing I could find:
http://help.adobe.com/en_US/AIR/1.5/devappshtml/WS5b3ccc516d4fbf351e63e3d118666ade46-7e74.html#WS5b3ccc516d4fbf351e63e3d118666ade46-7e72
It looks like you can extend the HTMLLoader as you suggested and override javascript callbacks. I haven't tried this so I'm not sure but it's worth giving it a whirl.
After debug and test, I found that the HTMLLoader has a property window. This window is like javascript DOM window.
You can use following code to disable alert.
public class MyHTMLLoader extends HTMLLoader
{
override public function MyHTMLLoader()
{
super();
this.addEventListener(Event.HTML_DOM_INITIALIZE, htmlDomInitializedHandler);
}
protected function htmlDomInitializedHandler(event:Event):void
{
window.alert = function(){};
}
}
And modify your HTML component property htmlLoaderFactory to ...
<mx:HTML htmlLoaderFactory="{new ClassFactory(MyHTMLLoader)}" ...
Hope this will help you.
I'm building a video player using Flash CS4 (hereby referred to as "Flash") to create the graphic symbols and compiling and debugging with Flash Builder 4 ("FB4"). Here are the steps I take in my current workflow:
--Create the graphic symbols in Flash. I've created a few different symbols for the player, but I'll focus on just the play/pause button ("ppbutton") here.
--In the Library panel, I go to the ppbutton symbol's Linkage properties and link to a class named assets.PlayPauseButtonAsset that extends MovieClip. I do not actually have an assets package nor do I have a class file for PlayPauseButtonAsset as Flash will create them for me when I publish.
--In Flash's Publish settings, I set the project to export a SWC that will be used in FB4, called VideoPlayerAssets.swc.
--After the SWC is created, I create my FB4 project called "VideoPlayer" and add the SWC to my path. FB4 creates the class VideoPlayer in the default package automatically.
--In VideoPlayer.as, I import assets.*, which imports all of the symbol classes I created in Flash and are available via VideoPlayerAssets.swc. I can now instantiate the ppbutton and add to the stage, like this:
var ppbutton:PlayPauseButtonAsset = new PlayPauseButtonAsset();
addChild(ppbutton);
At this point ppbutton doesn't have any functionality because I didn't create any code for it. So I create a new class called video.controls.PlayPauseButtonLogic which extends assets.PlayPauseButtonAsset. I add some logic, and now I can use that new class to put a working ppbutton on the stage:
var ppbutton:PlayPauseButtonLogic = new PlayPauseButtonLogic();
addChild(ppbutton);
This works fine, but you may be asking why I didn't just link the ppbutton symbol in Flash to the video.controls.PlayPauseButtonLogic class in the first place. The reason is that I have a designer creating the UI in Flash and I don't want to have to re-publish the SWC from Flash every time I make a change in the logic. Basically, I want my designer to be able to make a symbol in Flash, link that symbol to a logically named class in Linkage properties, and export the SWC. I do not want to have to touch that .fla file again unless the designer makes changes to the symbols or layout. I'm using a versioning system for the project as well and it's cleaner to make sure only the designer is touching the .fla file.
So, finally, here's the issue I'm running into:
--As the design gets more complex, the designer is nesting symbols to position the video controls on the control bar. He creates a controlbar symbol and links it to assets.ControlBarAsset. The controlbar symbol contains the ppbutton symbol.
--The designer publishes the SWC and ControlBarAsset is now available in FB4. I create new class called video.controls.ControlBarLogic that extends assets.ControlBarAsset so I can add some logic to the controlbar, and I add the controlbar to the stage:
var controlbar:ControlBarLogic = new ControlBarLogic();
addChild(controlbar);
--This works, but the ppbutton doesn't do anything. That's because ppbutton, while inside controlbar, is still only linked to PlayPauseButtonAsset, which doesn't have any logic. I'm no longer instantiating a ppbutton object because it's part of controlbar.
That's where I'm stuck today. I can't seem to simply re-cast controlbar's ppbutton as PlayPauseButtonLogic as I get a Type error. And I don't want to have to make a class that has to instantiate each of the video player controls, the place them at their x and y values on the stage according to how the designer placed them, as that would require me to open the .fla and check the various properties of a symbol, then add those values to the code. If the designer made a change, I'd have to go into the code each time just to update those properties each time. Not good.
How do I re-cast nested symbols to use the logic classes that I create that extend the asset classes? Remember, the solution is not to link Flash symbols to actual classes so I don't have to keep recompiling the SWC, unless there's a way to do that without having to re-compile the SWC. I want the designer to do his thing, publish the SWC, and be done with it. Then I can take his SWC, apply my logic to his assets, and be able to debug and compile the final SWF.
Here is the solution that i use sometimes:
Instead of making PlayPauseButtonLogic extends PlayPauseButtonAsset, use this class as a warpper of PalyPauseButtonAsset, use composition instead of inheritance ! ; ).
You will get something like this in your ControlBarLogic class:
//constructor exemple
public function ControlBarLogic(){
//all logic of PPButton is inside PlayPauseButtonLogic
//you just pass a reference to the PlayPauseButtonAsset button contained inside ControlBarAsset
var ppButtonLogic: PlayPauseButtonLogic=new PlayPauseButtonLogic(refToButtonAsset)
//the warper class can extends EventDispatcher so you will be able to listen to custom or redisatched events
ppButtonLogic.addEventListener("ppPause",onPause)
}
hope it will help you
You can have two classes, one holding functionality and the other providing its graphical implementation (asset/skin)
Have PlayPauseButtonLogic extend AssetWrapper.
A simple way to solve your issue regarding event listeners, you can do the following:
package {
import flash.display.DisplayObjectContainer;
import flash.events.Event;
import flash.events.IEventDispatcher;
public class AssetWrapper implements IEventDispatcher {
private var _skin:DisplayObjectContainer;
public function AssetWrapper( skin:DisplayObjectContainer = null ) {
if ( skin ) setSkin(skin);
}
public function setSkin(skin:DisplayObjectContainer):void{
_skin = skin;
}
public function dispatchEvent(event:Event):Boolean{
_skin.dispatchEvent(event);
}
public function hasEventListener(type:String):Boolean{
return _skin.hasEventListener(type);
}
public function willTrigger(type:String):Boolean{
return _skin.willTrigger(type);
}
public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void{
_skin.removeEventListener(type, listener, useCapture);
}
public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void{
_skin.addEventListener(type, listener, useCapture, priority, useWeakReference);
}
}
}
EDIT:
You can then, of course, just add as many properties/methods to AssetWrapper that delegate to the DisplayObject (skin) as you need. It also gives you more control onto those properties/methods.
i.e:
public function get x( ):Number {
return _skin.x;
}
public function set x( v:Number ):void {
if ( _skin.x = v ) return;
if ( _useWholePixels ) _skin.x = Math.round(v);
else _skin.x = v;
}
That way, for instance, you can tween your AssetWrapper instance directly. Also, you can control if you want it to be placed in round numbers (x=100) or not (x=100.5)
For methods, just the same idea:
public function addChild( child:DisplayObject ):DisplayObject {
return _skin.addChild( child );
}
Then to use it, you would extend AssetWrapper and implement a concrete behavior:
package {
import flash.display.DisplayObjectContainer;
import flash.events.MouseEvent;
public class SimpleButton extends AssetWrapper {
public function SimpleButton( skin:DisplayObjectContainer = null ) {
super(skin)
}
override public function setSkin( skin:DisplayObjectContainer):void {
super.setSkin( skin );
addEventListener(MouseEvent.ROLL_OVER, _onRollOver );
addEventListener(MouseEvent.ROLL_OUT, _onRollOut );
}
protected function _onRollOver(e:MouseEvent):void {
_skin.alpha = .5;
}
...
}
And you would use it as follows:
//you can get your graphical assets in many different ways
var buttonSkin:Sprite = new LibraryButtonSkin
//or
var ButtonSkinClass:Class = this.loaderInfo.applicationDomain.getDefinition("SimpleButtonSkin") as Class;
buttonSkin = new ButtonSkinClass;
var button:SimpleButton = new SimpleButton(buttonSkin);
button.addEventListener(MouseEvent.CLICK, _handleButton);
It is just a guide, in the real implementation you want to make sure you check for things like if a skin already exists, then remove all added listeners. You would probably could listen for an ADDED_TO_STAGE event and trigger a initialize method...
Also is a great to clean up after your instance by implement a destroy() method where you make sure all added listeners are removed and null/stop things like timers, sounds, etc.
Wow all the flow and we sunk in the finish line....
well, what about something like this
AbstractButtonBehavior
PlayButtonBehavior extends...
The trick, the graphic components should all implement some interface that allow them to pass a behavior at instantiation time, or even better, at runtime. The you just plug the login in, the logic will always remain outside and the poor assets will keep asking or answering to the same interface call, allowing you to work outside them.
could be?.
I have the following problem.
In my application I have several modules and each of them have components CollapsableTitleWindow (extends Panel). After opening the window it is added to the container which is in the main application (CollapsableTitleWindowContainer). In these windows you can open another window (and so on).
Now, what is the problem.
When I change (reload) any module and I want to open a new window (sub window) with the already loaded window I get this error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at mx.containers::Panel/layoutChrome()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\containers\Panel.as:1405]
at com::CollapsableTitleWindow/layoutChrome()[D:\Flex 3 Workspace\WesobCrm\src\com\CollapsableTitleWindow.as:216]
at mx.core::Container/updateDisplayList()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:2867] (...)
Indicates that the main applications have object Panel
Please help.
P.S. I found a similar problem on http://www.nabble.com/Flex-Module-issue-with-Panel-td20168053.html
ADDED:
I extendes the Panel class and do something like that:
override protected function layoutChrome(unscaledWidth:Number, unscaledHeight:Number):void
{
use namespace mx_internal;
if(!(mx_internal::titleBarBackground is TitleBackground)) {
mx_internal::titleBarBackground = new TitleBackground();
}
super.layoutChrome(unscaledWidth, unscaledHeight);
}
But now i had something like that:
Before
(source: ak.bx.pl)
After
(source: ak.bx.pl)
You can see that it loos style declaration.
I found a solution but it is bad pratice:
I add in my main application
public function getProductWindow():ProductWindow {
return new ProductWindow();
}
And change in the module:
From
var productWindow:ProductWindow = new ProductWindow();
To
var productWindow:ProductWindow = Application.application.getProductWindow();
If anyone have a better solution ?