Monthly Archives: April 2016

TweetWrap: For the TweetDeck desktop lovers running Windows 10

FacebookTwitterGoogle+Share

Download TweetWrap for Windows 10 here: https://www.microsoft.com/en-us/store/apps/tweetwrap/9nblggh4nbpp

A couple of weeks ago I saw a notice that TweetDeck for Desktop was going to be discontinued on April 15 and even if it was already installed it would stop working. I have tried several other Twitter apps for Windows 10, including the official Twitter app, Tweetium, Tweet It!, and more, but each falls short for my needs in one way or another. The biggest reason in these apps is because I value my screen real estate, and even at the smallest font and scale of the app, I can’t seem to fit as much information as I want to. Could be just me, if you are happy with your twitter experience, this isn’t for you.

Personally every time over the past year or so that I reset my laptop or got a new one, the first thing I did was go find an installer for an old version of TweetDeck so I could install it. This ended when Twitter disabled even that option on April 15.

I noticed that the TweetDeck desktop app and the web site are extremely similar. Actually I would be shocked if the old desktop app wasn’t just a wrapper for the web site, so I thought why can’t I just wrap it myself in an app? That was when TweetWrap was born.

Note: After I created TweetWrap, Simon Bisson (@sbisson on twitter) told me about the TwitDuck app written by Mark Allan (@markxa on twitter) which was doing basically the same thing. I was far enough along in my app that I felt I should publish it anyway.

I have no goal or motive with this app except having a twitter client on Windows 10 desktop that I can use. So you may say why not just use the web version? Again I value my screen real estate and I don’t like having and address bar or tabs taking away from that when I just want an app. Also it’s easier to launch and manage.

I have also published the source code to GitHub with a hope that others will contribute to make it better. You can get the source code here: https://github.com/billreiss/TweetWrap 

The main glaring issues I see with the app at this point are that the scrollbars show up on hover, instead of either being hidden always or showing always like they are when you run the TweetDeck site in the browser. I don’t know why this happens and fixing this would be a huge improvement. Also if there was a way to enable push notifications I think that would be something a lot of users would want. Let’s work together to provide a quality Twitter experience for Windows 10 users.

Note: Yes I know there may be other options for this, I think Chrome has a way to launch a web site without all the other stuff. Please post details on other options to the comments section. Thanks!

Xamarin Forms: A Simple Circular Progress Control

Source code for this sample is available on GitHub here: https://github.com/billreiss/xamlnative/tree/master/XamarinForms/CircularProgress

Recently in a Xamarin Forms app I needed to show progress of an operation as a circle that would fill itself in as the progress completed. Something like this:

10uk8w_thumb.gif

 

The built in Xamarin Forms Progress control is a line, and can’t easily be changed to show a circle. I looked at some different options, including finding a native control for the different platforms and render them using custom renderers, or to use a component for the component store, or something on NuGet, but didn’t really find anything suitable. So I did my own thing, and I’m really happy with how it turned out, then I wanted to share what I came up with. Feel free to riff on this design and come up with your own variations.

First I thought about vector graphics. There doesn’t seem to be any built in support for this in Xamarin Forms, and I would have to do custom renderers for each platform. Then I started thinking about using images to do the animation. It certainly would be better with vector graphics, but maybe this would be “good enough”. Then I considered how many different images I would need to make it look smooth. A dozen? More? Something like this?

th_thumb.jpg

 

* this is a copy of a circle sprite sheet published here

I was able to come up with a solution that uses two images. Actually two instances each of two images, so four images total. Combining these images with rotation and changing which images show in front of each other, we can show any percentage of progress smoothly.

The two images we need are semicircles, one for completed progress, and one for incomplete progress (you can download them here https://github.com/billreiss/xamlnative/tree/master/XamarinForms/CircularProgress/CircularProgress/CircularProgress.Droid/Resources/drawable):

progress_pending_thumb.png progress_done_thumb.png

 

These are two semicircles saved as PNG format with transparent backgrounds. First let’s consider the case between 0 and 50% complete. Let’s call the first image the “completed” image, and the second is the “pending” image. We will need three images to handle the case from 0 to 50%, one “completed” and two “pending” images.

The completed image (in the code we’ll call it “progress1”) looks like this:

image.png

 

Then on top of that we display a “pending” image (in the code we’ll call it “background1” looks like this:

image.png

 

With these directly on top of each other, the darker blue circle is completely covered and not visible.

Then we add another copy of this image, but rotated 180 degrees:

image.png

 

This makes a solid light blue circle, which is what we expect to see at 0% complete.

image.png

Then if we rotate the instance of “background1”, we will expose part of the dark blue semicircle. Part of “background1” will overlap “background2”, but that’s ok, since they are the same color you won’t be able to tell.

image.png

 

Once we get to 50%, then things change a little. Now we need 2 instances of the dark blue image, one rotated 180 degrees, and one instance of the light blue image. This light blue image will reveal portions of the 180 degree rotated dark blue image similar to how the less than 50% scenario worked, and the non-rotated dark blue image needs to be in front of this pending image, and the rotated completed image needs to behind the pending image. So the light blue image is sandwiched between the other two, with the non-rotated image all the way to the front, otherwise as the pending image rotates it would obscure this “half-completed” part of the progress.

Are you totally confused yet? Thankfully it’s actually not a lot of code. We will have a dependency property called “Progress” that goes from 0 to 1 to match how the built-in progress control works. And then when that value changes, we do the right thing showing and rotating images to get the right effect.

IMPORTANT NOTE: If you create your Xamarin Forms project from scratch using the built in Visual Studio template, make sure you use NuGet to update Xamarin Forms to the latest stable version. There was a bug in Xamarin Forms on Windows platforms that would make this code not have the desired result.

Here is the code for the circular progress control:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace CircularProgress
{
    public class CircularProgressControl : Grid
    {
        View progress1;
        View progress2;
        View background1;
        View background2;
        public CircularProgressControl()
        {
            progress1 = CreateImage("progress_done");
            background1 = CreateImage("progress_pending");
            background2 = CreateImage("progress_pending");
            progress2 = CreateImage("progress_done");
            HandleProgressChanged(1, 0);
        }

        private View CreateImage(string v1)
        {
            var img = new Image();
            img.Source = ImageSource.FromFile(v1 + ".png");
            this.Children.Add(img);
            return img;
        }

        public static BindableProperty ProgressProperty =
    BindableProperty.Create("Progress", typeof(double), typeof(CircularProgressControl), 0d, propertyChanged: ProgressChanged);

        private static void ProgressChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var c = bindable as CircularProgressControl;
            c.HandleProgressChanged(Clamp((double)oldValue, 0, 1), Clamp((double)newValue, 0, 1));
        }

        static double Clamp(double value, double min, double max)
        {
            if (value <= max && value >= min) return value;
            else if (value > max) return max;
            else return min;
        }

        private void HandleProgressChanged(double oldValue, double p)
        {
            if (p < .5)
            {
                if (oldValue >= .5)
                {
                    // this code is CPU intensive so only do it if we go from >=50% to <50%
                    background1.IsVisible = true;
                    progress2.IsVisible = false;
                    background2.Rotation = 180;
                    progress1.Rotation = 0;
                }
                double rotation = 360 * p;
                background1.Rotation = rotation;
            }
            else
            {
                if (oldValue < .5)
                {
                    // this code is CPU intensive so only do it if we go from <50% to >=50%
                    background1.IsVisible = false;
                    progress2.IsVisible = true;
                    progress1.Rotation = 180;
                }
                double rotation = 360 * p;
                background2.Rotation = rotation;
            }
        }

        public double Progress
        {
            get { return (double)this.GetValue(ProgressProperty); }
            set { SetValue(ProgressProperty, value); }
        }
    }
}

We also need to put the images in the correct images folder for each platform. For iOS this is the Resources folder, and the Build Action should be set to BundleResource. For Android it’s the Resources/drawable folder and the type is AndroidResource. For the Windows platforms they go in the root folder.

Then to use the control. Assume we have a Xamarin Forms XAML page called MainPage.xaml, we can load the control like this:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="CircularProgress.MainPage" 
             xmlns:local="clr-namespace:CircularProgress" BackgroundColor="White">
  <Grid>
    <local:CircularProgressControl x:Name="progressControl" Progress="0" HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="60" HeightRequest="60"/>
  </Grid>
</ContentPage>

And in the code behind we can have a timer that increments the Progress property a bit at a time from 0 to 1 and then starts over:

namespace CircularProgress
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            Xamarin.Forms.Device.StartTimer(TimeSpan.FromSeconds(.02), OnTimer);
        }

        private bool OnTimer()
        {
            var progress = (progressControl.Progress + .01) ;
            if (progress > 1) progress = 0;
            progressControl.Progress = progress;
            return true;
        }
    }
}

Now if you run the app you should see something like the animated image at the top of this post. No custom renderers and it runs on every Xamarin Forms platform!

Visual Studio 2015 Update 2 XAML Debugging Improvements

I felt one of the coolest things in Visual Studio 2015 for XAML developers was the Live Visual Tree Debugger. In the past there were tools like Snoop and XAML Spy which were so very useful but it was exciting to see this kind of functionality built in to Visual Studio.

Visual Studio 2015 Update 2 was announced and released at the BUILD conference last week, and when I installed it (download it here) and ran my app in the debugger, I saw an unexpected surprise. Overlaid on top of the app window was a new set of buttons:

image

The first button is to go to the Live Visual Tree debugger window in Visual Studio, not too interesting.

image

The second button enables selection. This one is really interesting, because when you click on a visual element in your app, it will be selected in the visual tree debugger. This button was already available in Visual Studio in the Live Visual Tree pane, but it’s a lot more convenient to have it right in your app.

image

The third button, “Display Layout Adorners”, I’m not really sure how useful this is, but maybe I’m missing something.

These buttons also exist inside Visual Studio 2015 in the Live Visual Tree pane just like they did before, but there is a new button which lets you turn on and off the toolbar that shows up inside your app.

image

If you are debugging an app with source code, then in the Live Visual Tree pane, beside any element can be resolved to the corresponding XAML file, you’ll see an icon that lets you navigate to the XAML definition:

image

Another thing I think is pretty interesting is that you can debug other XAML based applications even if they aren’t yours. One example of this is the Settings dialog in Windows 10. If you open the settings dialog, and then switch to Visual Studio 2015 Update 2 and you select Debug and then Attach to Process, you should be able to pick to debug SystemSettings.exe:

image

You can do the same with the Edge browser, Groove Music, the Store app, or a bunch of other apps. Most of the built in Windows 10 dialogs use XAML. So if you attach the debugger, you should see the same toolbar show up inside this app:

image

The one difference is that since you don’t have the source code, you won’t see the buttons next to elements that let you navigate to the XAML, but you should still be able to see all of the visual elements in the Live Visual Tree pane.

UPDATE: It works for WPF too! Here is a debugger attached to another instance of Visual Studio (Visual Studio uses WPF for its user interface):

image

By running this tool against other apps you can see how they implemented their XAML and it can give you some ideas for your own app.