facebook / react-native

A framework for building native applications using React

Home Page:https://reactnative.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Android] setClipChildren doesn't seems to resolve overflow

felippepuhle opened this issue · comments

Is this a bug report?

Yes

Have you read the Contributing Guidelines?

Yes

Environment

OS: macOS High Sierra 10.13.1
Node: 6.10.3
Yarn: 1.2.1
npm: 3.10.10
Watchman: 4.7.0
Xcode: Xcode 9.1 Build version 9B55
Android Studio: 3.0 AI-171.4443003

Packages: (wanted => installed)
react: 16.0.0 => 16.0.0
react-native: 0.50.3 => 0.50.3

Target Platform: Android

Steps to Reproduce

  1. Create a custom native component that overrides setClipChildren on Android, ex: ViewWithoutOverflow
  2. Create a JS component using ViewWithoutOverflow as wrapper and specifying some width/height
  3. Add a View inside with position absolute and greater width

Expected Behavior

Lately, we're having some troubles with overflow on Android devices (as expected). I was able to fix it adding <item name="android:clipChildren">false</item> on src/main/res/values/styles.xml:

success

That was terrible: my animations started to show a very bad FPS. So, I decided to create a native component that handles this, and use only in some places... but I couldn't make it work yet.

Can I get the same result presented changing styles.xml with setClipChildren on a custom native component?

Actual Behavior

With the native component(ViewWithoutOverflow) the overflow: hidden still stands.

error

Reproducible Demo

ViewWithoutOverflowPackage.java

public class ViewWithoutOverflowPackage implements ReactPackage {

    // @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }

    // @Override
    public List<Class<? extends JavaScriptModule>> createJSModules() {
        return Collections.emptyList();
    }

    // @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Arrays.<ViewManager>asList(
                new ViewWithoutOverflowManager()
        );
    }
}

ViewWithoutOverflowManager.java

public class ViewWithoutOverflowManager extends ViewGroupManager<ViewWithoutOverflowLayout> {

    @Override
     protected ViewWithoutOverflowLayout createViewInstance(ThemedReactContext reactContext) {
        return new ViewWithoutOverflowLayout(reactContext);
     }

    @Override
    public String getName() {
        return "ViewWithoutOverflow";
    }

}

ViewWithoutOverflowLayout.java

public class ViewWithoutOverflowLayout extends ReactViewGroup {

    public ViewWithoutOverflowLayout(Context context) {
        super(context);

        setClipChildren(false);
        setClipToPadding(false);
    }

}

ViewWithoutOverflow.android.js

import { requireNativeComponent } from 'react-native';

export default requireNativeComponent('ViewWithoutOverflow', null);

DemoScreen.js

import * as React from 'react';
import { View } from 'react-native';

import ViewWithoutOverflow  from './ViewWithoutOverflow';

class DemoScreen extends React.PureComponent {
  render() {
    return (
      <ViewWithoutOverflow style={{
        width: 200,
        height: 200,
        backgroundColor: 'green',
      }}>
        <View style={{
          position: 'absolute',
          left: 0,
          top: 0,
          width: 400,
          height: 100,
          backgroundColor: 'red',
        }} />
      </ViewWithoutOverflow>
    );
  }
}

export default DemoScreen;

I'm closing this issue... @sibelius did the trick:

ViewWithoutOverflowLayout.java

public class ViewWithoutOverflowLayout extends ReactViewGroup {

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

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        try {
            ((ViewGroup) getParent()).setClipChildren(false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

Unfortunately, views that draw outside the parent does't seem to react to touch input

@felippepuhle Would you be willing to formally release this as a component via npm for those of us less comfortable working with Android codebases?

any workaround regarding this? @Kebabpizza I realised that's a real bummer because imagine I have dropdown coming from react-native-view-overflow and I can't give touch ability to view outside of parent. 😞