Kotlin RC and kotlinx

I’ve been toying with Kotlin for a while. Yesterday RC was released, making it one step closer to have a stable version.

One small change that has made me scratch my head a little, even if I read the solution, has been the changes regarding Kotlin Extensions. This had been integrated with the main Kotlin plugin (instead of being a separated plugin) but on RC you need to change your Gradle file a little to keep using it.

The symptom is that you find an “Unresolved reference: kotlinx” plus others that come from the same namespace. Resolution is easy: in the announcement for the release Kotlin 1.0 Release Candidate is Out! in the section Tooling, it reads (bold is mine):

To enable Android Extensions in Gradle in a more idiomatic way, we now say:

apply plugin: 'kotlin-android-extensions'

in the build.gradle file (individually for each project).

The old way doesn’t work any more and prints fixing instructions to the output.

So, I haven’t found this instructions, but the solution is easy: apply the new kotlin-android-extensions plugin right after the kotlin-android plugin in your gradle file. Usually, the end result will be like this:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

After that you just need to sync your Gradle configuration and rebuild the whole project.

FizzBuzz in CSS

Wat

Fun moment: Wat

Re-enabling Xcode plugins

After updating my Xcode, I noticed that plugins got disabled. To reenable them, the easiest way is just “touching” all the plugin directories:

$ cd ~/Library/Application\ Support/Developer/Shared/Xcode/Plug-ins
$ touch *

After that, restart Xcode and you will get a dialog asking if plugins should be loaded.

An alternate take on this is can be found here: Re-enable Alcatraz on Xcode 6.3.2 or Newer

Additional tip: if the update was the OS, maybe this StackOverflow answer can be also useful: CocoaPods doesn’t work after upgrading Mac OS X EI Capitain.

UPDATE: I’ve updated to Xcode 7.2 today, and suddenly all the plugins stopped to work. There is an update for Alcatraz. See also this tweet.

UPDATE2: There is a new upgrade for Alcatraz for Xcode 7.3. See this tweet. You need to first update it, then “touch” the plugins (see above), execute:

$ defaults delete com.apple.dt.xcodebuild DVTPlugInManagerNonApplePlugIns-xcodebuild-7.3
$ defaults delete com.apple.dt.Xcode DVTPlugInManagerNonApplePlugIns-Xcode-7.3

Additionally, I guess that some plugins need an update, because they are not working (for example CocoaPods).

Easily manage windows in OS X

I’ve been using OS X for many years already, and as my primary computer OS for almost a year. Before that, I used to spend time with Windows (like 90% of it), Linux (for server) and OS X.

There are two things that I missed after switching from Windows (last version I regularly used was 8.1) to OS X (I started to regularly use it on Tiger), being a heavy keyboard user: the way window cycling works on Windows, and Windows snap (available since Windows 7, including shortcuts).

Window switch

Window switch shortcut on Windows (Alt+Tab) cycles through all your windows, in usage order, but on OS X (Cmd+Tab) cycles through applications. There is a second shortcut, which usually is assigned to Cmd+`. This shortcut is quite cumbersome, at least on Spanish keyboard layout (maybe also on English layout too): as soon you enter in a text field of any kind, if you press this shortcut you get the ` character, waiting for you to complete an accented letter (yes, in Catalan and Spanish languages we have such a thing). Additionally you cycle through your windows immediately, without preview, and without remembering your usage order.

There are two solutions here:

  • change the shortcut in System Preferences (preview and usage order still missing here),
  • use Witch (thanks to Jaume Sánchez for pointing me this out).

I prefer using Witch, as it has lots of options, allowing you to use a switcher more like Windows one, making no distinction between windows and apps, or use it the way I do, which is to use it as an improvement to OS X default way of switching between windows inside an application. BTW I use Alt+Cmd+Tab as this shortcut, and doesn’t conflict with any other shortcut, working all the time.

Windows Snap

When working with many windows, sometimes is useful to be able to “snap” windows to one side of the screen or the other. This feature is really useful on Windows (starting from 7), but I’ve been missing it on OS X since the beginning. Also, maximizing not always maximizes in both directions, but only in vertical (depends on the application). Finally, on OS X “El Capitan”, maximize button has changed to fullscreen as the default option, having to press Alt to maximize. This version of OS X also includes a feature like Snap, but only works for fullscreen apps.

So, recently I found a way of overcoming this and having nice shortcuts “a-la-Windows”: Spectacle. This nice app sits in your menu bar and helps you to quickly resize your windows (snap, fullscreen, even quarter of screen snap), move them between screens, even undo and redo this actions!

Four things you probably didn’t know about C++ (and C)

I’ve recently stumbled upon this interesting post of curious features of C++ I didn’t know of (being a C/C++ programmer for so many years!).

One of the techniques I find really amazing (even when sometimes this kind of cleverness comes to bite you in the ass afterwards!) is Duff’s device. I’ve done my fair share of loop unrollings and clever tricks on C, but I find this an step further!

In-depth article on Android touch events handling

Sometimes you need to intercept touches for a given ViewGroup, to temporarily change or disable it’s behavior. For example, recently I had to do this to temporarily intercept events for a RecyclerView during a tutorial, instructing the user how to select a particular item.

In this case, I could simply add an overlaid Layout on top of everything, but to keep as close to the real thing as possible, I decided to intercept the touch events at the RecyclerView level. The problem is, how to detect if the touch event needs to be intercepted or not. Two possible solutions came to my mind:

  • Intercept (or somehow disable) the events on each individual item, except on the one we’re interested on receiving it. For me it’s a bit messy to have this logic scattered.
  • Intercept the events on the RecyclerView, and check if the event belongs to the child, to allow further processing.

So, I decided to go for the second solution. To do that, I investigated a bit more in depth how touch events are handled in Android. This a really interesting article on how this happens: Understanding Android Input Touch Events System Framework (dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent, OnTouchListener.onTouch). Also, it is really useful to see the real code on how a ViewGroup handles this. Even if I could download Android source code from the Android Open Source Project web site, I didn’t really felt like it. So I found this copy online.

The interesting part for us is ViewGroup#dispatchTouchEvent(MotionEvent), and specifically in the loop where it iterates all the child and checks if the touch event is within the bounds of this child.

Based on this, I extracted the relevant code, which boils down to retrieving the hit rectangle of the child we want to allow processing the event, and checking it against the touch target. This class has to be overridden and the getAllowedChildView() method implemented, returning the child we’re interested in allowing the touch events go through.

public class CustomRecyclerView extends RecyclerView {

    private static final String LOG_MARKER = CustomRecyclerView.class.getName();

    private boolean scrollEnabled = true;

    public CustomRecyclerView(Context context) {
        super(context);
    }

    public CustomRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void setEnabledRecycleScroll(final boolean enable) {

        if (scrollEnabled == enable) {
            Logger.getInstance().debug(LOG_MARKER, "RecyclerView scrolling is already " +
                    (enable ? "enabled" : "disabled") + ", skipping");
            return;
        }

        scrollEnabled = enable;

        if (!enable) {
            Logger.getInstance().debug(LOG_MARKER, "Disabling RecyclerView scrolling");
            addOnItemTouchListener(disablerListener); // disables scrolling
        } else {
            Logger.getInstance().debug(LOG_MARKER, "Enabling RecyclerView scrolling");
            removeOnItemTouchListener(disablerListener); // scrolling is enabled again
        }

    }

    // Override this method to return the child we're interested in allowing touch events
    // to go through
    abstract protected View getAllowedChildView();

    private RecyclerView.OnItemTouchListener disablerListener =
            new RecyclerView.OnItemTouchListener() {
        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent ev) {

            // Inspired by ViewGroup#dispatchTouchEvent(MotionEvent). See
            // http://codetheory.in/understanding-android-input-touch-events/ and
            // http://www.netmite.com/android/mydroid/frameworks/base/core/java/android/view/ViewGroup.java
            final int action = ev.getAction();
            if (action == MotionEvent.ACTION_DOWN) {
                final float scrolledX = ev.getX() + CustomRecyclerView.this.getScrollX();
                final float scrolledY = ev.getY() + CustomRecyclerView.this.getScrollY();
                final Rect frame = new Rect();
                View allowedChildView = getAllowedChildView();
                if (allowedChildView != null) {
                    allowedChildView.getHitRect(frame);
                    if (frame.contains((int) scrolledX, (int) scrolledY)) {
                        // Do not intercept the touch events for this child
                        return false;
                    }
                }
            }

            return true;
        }

        @Override
        public void onTouchEvent(RecyclerView rv, MotionEvent e) {
        }
    };

}