Index: src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java	(revision 15795)
+++ src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java	(working copy)
@@ -54,6 +54,7 @@
 import org.openstreetmap.josm.gui.MapView;
 import org.openstreetmap.josm.gui.SideButton;
 import org.openstreetmap.josm.gui.dialogs.layer.ActivateLayerAction;
+import org.openstreetmap.josm.gui.dialogs.layer.CycleLayerAction;
 import org.openstreetmap.josm.gui.dialogs.layer.DeleteLayerAction;
 import org.openstreetmap.josm.gui.dialogs.layer.DuplicateAction;
 import org.openstreetmap.josm.gui.dialogs.layer.LayerListTransferHandler;
@@ -141,6 +142,8 @@
     private final ActivateLayerAction activateLayerAction;
     private final ShowHideLayerAction showHideLayerAction;
 
+    private final CycleLayerAction cycleLayerAction;
+
     //TODO This duplicates ShowHide actions functionality
     /** stores which layer index to toggle and executes the ShowHide action if the layer is present */
     private final class ToggleLayerIndexVisibility extends AbstractAction {
@@ -329,6 +332,9 @@
         // Show/Activate layer on Enter key press
         InputMapUtils.addSpacebarAction(layerList, showHideLayerAction);
 
+        // Cycle layer action
+        cycleLayerAction = new CycleLayerAction();
+
         createLayout(layerList, true, Arrays.asList(
                 new SideButton(moveUpAction, false),
                 new SideButton(moveDownAction, false),
@@ -388,6 +394,7 @@
         DISPLAY_NUMBERS.removeListener(visibilityWidthListener);
         ExpertToggleAction.removeExpertModeChangeListener(visibilityWidthListener);
         layerManager.removeLayerChangeListener(visibilityWidthListener);
+        cycleLayerAction.destroy();
         super.destroy();
         instance = null;
     }
Index: src/org/openstreetmap/josm/gui/dialogs/layer/CycleLayerAction.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/layer/CycleLayerAction.java	(nonexistent)
+++ src/org/openstreetmap/josm/gui/dialogs/layer/CycleLayerAction.java	(working copy)
@@ -0,0 +1,100 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.dialogs.layer;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import javax.swing.JMenuItem;
+
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.layer.ImageryLayer;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.Layer.LayerAction;
+import org.openstreetmap.josm.gui.layer.MainLayerManager;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.Shortcut;
+
+/**
+ * Allow users to cycle between adjacent layers easily
+ *
+ * @author Taylor Smock
+ * @since xxx
+ */
+public class CycleLayerAction extends JosmAction implements LayerAction {
+    private static Shortcut cycleUp = Shortcut.registerShortcut("core:cyclelayerup", tr("Cycle layers down"),
+            KeyEvent.VK_BRACELEFT, Shortcut.SHIFT);
+    private static Shortcut cycleDown = Shortcut.registerShortcut("core:cyclelayerdown", tr("Cycle layers up"),
+            KeyEvent.VK_BRACERIGHT, Shortcut.SHIFT);
+
+    /**
+     * Create a CycleLayerAction that cycles through layers that are in the model
+     */
+    public CycleLayerAction() {
+        super(tr("Cycle layers"), "dialogs/next", tr("Cycle through layers"), cycleDown, true,
+                "cycle-layer", false);
+        MainApplication.registerActionShortcut(this, cycleUp); // cycleDown gets registered by JosmAction
+        new ImageProvider("dialogs", "next").getResource().attachImageIcon(this, true);
+        putValue(SHORT_DESCRIPTION, tr("Cycle through visible layers."));
+        putValue(NAME, tr("Cycle layers"));
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        MainLayerManager manager = MainApplication.getLayerManager();
+        List<Layer> managerLayers = manager.getLayers().stream().filter(layer -> !(layer instanceof ImageryLayer))
+                .collect(Collectors.toList());
+        if (managerLayers.isEmpty())
+            return;
+        int key = KeyEvent.getExtendedKeyCodeForChar(e.getActionCommand().charAt(0));
+        Shortcut shortcut = Shortcut
+                .findShortcut(key, cycleDown.getAssignedModifier())
+                .orElse(null);
+
+        List<Layer> layers;
+        if (cycleDown.equals(shortcut)) {
+            int index = managerLayers.indexOf(manager.getActiveLayer());
+            int sublist = index < managerLayers.size() ? index + 1 : index;
+            if (index >= managerLayers.size() - 1) {
+                index = 0;
+                sublist = 0;
+            }
+            layers = managerLayers.subList(sublist, managerLayers.size());
+        } else {
+            layers = new ArrayList<>(managerLayers);
+            Collections.reverse(layers);
+            int index = layers.indexOf(manager.getActiveLayer());
+            int sublist = index < managerLayers.size() - 1 ? index + 1 : 0;
+            layers = layers.subList(sublist, layers.size());
+        }
+        Layer layer = layers.stream().filter(Layer::isVisible).filter(tlayer -> !(tlayer instanceof ImageryLayer))
+                .findFirst()
+                .orElse(manager.getActiveLayer());
+
+        if (layer != null)
+            manager.setActiveLayer(layer);
+    }
+
+    @Override
+    public boolean supportLayers(List<Layer> layers) {
+        return true;
+    }
+
+    @Override
+    public Component createMenuComponent() {
+        return new JMenuItem(this);
+    }
+
+    @Override
+    public void destroy() {
+        super.destroy();
+        MainApplication.unregisterActionShortcut(this, cycleUp);
+    }
+}
