famous: scrollview within scrollview

2020-06-29 00:13发布

问题:

I'm trying to create a layout (using famous.js) similar to the BBC News native app; a vertical ScrollView, within which are numerous horizontal ScrollViews. I've got both 'working' to the extent that everything renders and the horizontal scrollers work perfectly. My issue is that the vertical scroll event won't fire if the user swipes a surface within a horizontal ScrollView. If i touch an area outside the horizontal scrollers, the vertical scroller will do its job and scroll... vertically

Does anyone know what i'm missing? I have a feeling that a RenderNode may be needed, but have had no luck so far. I'm just getting to grips with Famous. What i've seen so far is amazing, but not being able to figure this out is really getting to me...

Uber thanks in advance if anyone can help...

    /*globals define*/
    define(function(require, exports, module) {

        // import dependencies
        var Modifier           = require('famous/core/Modifier');
        var Engine             = require('famous/core/Engine');
        var Surface            = require('famous/core/Surface');
        var HeaderFooterLayout = require('famous/views/HeaderFooterLayout');
        var Scrollview         = require('famous/views/Scrollview');
        var ContainerSurface   = require('famous/surfaces/ContainerSurface');

        var mainContext = Engine.createContext();

        var layout = new HeaderFooterLayout({
            headerSize: 50,
            footerSize: 50
        });

        // create app header and add to layout
        var appHeader = new ContainerSurface({
            size: [undefined, 50],
            classes: ['app-header']
        });
        appHeader.add(new Surface({
            size: [undefined, 50],
            content: 'Site Name',
            classes: ['app-header__title'],
            properties: {
                lineHeight: '50px',
                textAlign: 'center'
            }
        }));
        layout.header.add(appHeader);

        // create page container surface
        var page = new ContainerSurface({
            properties: {
                top: '0'
            }
        });

        // returns a horizontal ScrollView containing 
        function createCategory() {
            var categoryScroll = new Scrollview({
                direction: 0,
            });
            var surfaces = [];
            categoryScroll.sequenceFrom(surfaces);
            for (var i = 0, temp; i < 7; i++) {
                var temp = new Surface({
                    size: [128, 128],
                    content: 'surface' + (i + 1),
                    properties: {
                        backgroundColor: '#fff',
                        borderColor: '#303030',
                        borderStyle: 'solid',
                        borderWidth: '0px',
                        borderRightWidth: '4px',
                        borderLeftWidth: '4px'
                    }
                });
                temp.pipe(categoryScroll);
                surfaces.push(temp);
            }
            return categoryScroll; 
        }

        // returns a vertical page scroll
        function createPageScroll() {

            // create array of horizontal ScrollViews
            categories = [];
            for (var i = 0; i < 7; i++) {
                categories.push(createCategory());
            };

            var pageScroll = new Scrollview();
            var surfaces = [];
            for (var i = 0; i < 7; i++) {
                temp = new ContainerSurface({
                    size: [window.innerWidth, 136],
                });
                temp.add(categories[i]);
                surfaces.push(temp);
                pageScroll.sequenceFrom(surfaces);
                temp.pipe(pageScroll);
            };

            return pageScroll;
        }

        layout.content.add(createPageScroll());
        mainContext.add(layout);

    });

回答1:

I see you figured it out, but I thought I would post a clean working example for anyone that needed a starting point.. So here it is..

To answer the question, Yes, you needed to pipe your events from the surfaces to each of the scrollviews

var Engine              = require("famous/core/Engine");
var Surface             = require("famous/core/Surface");
var View                = require("famous/core/View");
var Scrollview          = require("famous/views/Scrollview");
var ContainerSurface    = require("famous/surfaces/ContainerSurface");

var context = Engine.createContext();

var surfaces1 = [];
var surfaces2 = [];

var scrollers = [];

scroll_v_cont = new ContainerSurface({
    size:[300,300],
    properties: { overflow: 'hidden' }
});

var scroll_v = new Scrollview({ direction: 1 });

scroll_v.sequenceFrom(scrollers);

scroll_v_cont.add(scroll_v);

var scroll_h1_cont = new ContainerSurface({
    size:[300,300],
    properties: {overflow: 'hidden'}
});


var scroll_h1 = new Scrollview({ direction: 0});

scroll_h1.sequenceFrom(surfaces1);

scroll_h1_cont.add(scroll_h1);


var scroll_h2_cont = new ContainerSurface({
    size:[300,300],
    properties: { overflow: 'hidden'}
})


var scroll_h2 = new Scrollview({ direction: 0})

scroll_h2.sequenceFrom(surfaces2);

scroll_h2_cont.add(scroll_h2);

scrollers.push(scroll_h1_cont);
scrollers.push(scroll_h2_cont);

for (var i = 0; i < 4; i++) {
    var surface1 = new Surface({
         content: "Surface: " + (i + 1),
         size: [300, 300],
         properties: {
             backgroundColor: "hsl(" + (i * 360 / 8) + ", 100%, 50%)",
             lineHeight: "200px",
             textAlign: "center"
         }
    });

    surface1.pipe(scroll_v);
    surface1.pipe(scroll_h1);
    surfaces1.push(surface1);

    var surface2 = new Surface({
         content: "Surface: " + (i + 1),
         size: [300, 300],
         properties: {
             backgroundColor: "hsl(" + (i * 360 / 8 + (360 / 8)*4) + ", 100%, 50%)",
             lineHeight: "200px",
             textAlign: "center"
         }
    });

    surface2.pipe(scroll_v);
    surface2.pipe(scroll_h2);
    surfaces2.push(surface2);

};

context.add(scroll_v_cont);


回答2:

the famous-flex FlexScrollView supports vertical & horizontal scrolling restrictions when embedding one scrollview in another. It is described in more detail at the bottom of the FlexScrollView tutorial:

https://github.com/IjzerenHein/famous-flex/blob/master/tutorials/FlexScrollView.md