如何根据选中状态动态更新MapMarker图像集合?

8

最近我一直在困扰这个问题,希望根据地图标记是否被选中/激活来动态更新地图标记图像(每个MapMarker都有一个类别,引用两个图像集interestIcons和interestIconsSelected中的活动图像或默认图像。基本上,我有一组MapMarkers,通过映射渲染出来,每个MapMarker是MapView.Marker的子组件。

我想在默认未选择/非激活状态下呈现所有MapMarkers,使用interestIcons中的默认图像,当选择时,该MapMarker图像应更改为从interestIconsSelected中选择的活动图像,当选择另一个MapMarker时,先前选择的应恢复为默认图像,新的应更改为所选图像。

目前,我可以使用默认图像呈现地图标记,但当选择地图标记时,图像似乎不会立即更改,除非您再次缩放/缩小以引起某种重新渲染,我希望单击MapMarker会立即导致图像更新。

MapScreen.js: 通过map渲染出所有MapView.Marker MapMarkers的MapView。

        <MapView
            ref={map => { this._map = map }}
            style={Styles.Map.map}
            initialRegion={this.props.region}
            onRegionChange={this.handleRegionChange}
        >
            {
                this.props.events
                    .filter(this.eventFilterTimeNearFuture)
                    .filter(this.eventFilterTimeNotPast)
                    .filter(this.eventFilterDistance)
                    .filter(this.eventFilterInterest)
                    .map(e =>
                        <MapView.Marker
                            key={e.id}
                            onPress={() => this.handleLocationPush(e)} // Set selected event state
                            coordinate={e.location}
                        >
                            <MapMarker
                                event={e}
                                size={this.state.markerSize}
                                selected={this.state.selectedEvent} // The selected event set by state call.
                            />
                        </MapView.Marker>
                    )
            }
            { !this.props.regionMock &&
                <MapView.Marker
                    key={'userLocation'}
                    coordinate={this.props.region}
                >
                    <MapMarker size={'user'} />
                </MapView.Marker>
            }
        </MapView>

MapMarker.js

import {interestIcons, interestColors, interestIconsSelected} from "../../utils/Icons";

import {Styles} from '../../StyleProvider';

class MapMarker extends React.Component {

constructor() {
    super();
    this.state = {
        initialized: false,
        active: false,
    };
};    

componentWillReceiveProps(nextProps) {
    if (!this.state.initialized) {
        console.log('initialization');            
        this.setState({initialized: true});
    }
    else {
        // If the nextProps.selected prop exists which it will
        if (nextProps.selected) {
            // If the nextProps.selected props id equals the this event id then selected else non-selected.
            if (nextProps.selected.id === nextProps.event.id) {
                console.log('SELECTED: ' + JSON.stringify(nextProps.selected));
                // set staae to active
                this.setState({
                    active: true
                });
                console.log(interestIconsSelected[nextProps.event.interest[0]]);
            } else {
                // set state to not active
                // console.log('NON-SELECTED: ' + JSON.stringify(nextProps.event));   
                this.setState({
                    active: false
                });                
            }
            this.forceUpdate();
        }
    }
}

 markerIcon(interest) {
    return this.state.active ? interestIconsSelected[interest] : interestIcons[interest];
 }

renderIcon() {
    if (this.props.event.type === 'Event') {
        return (
            <Image
                source={this.markerIcon(this.props.event.interest[0])}
                style={Styles.MapMarker.eventImage}
            />
        )
    }
}

componentWillReceiveProps(nextProps)仍在完善中,这表明当前选择的事件和所有未选择的事件都“很好”。

我尝试设置图像源来使用this.state.image,然后在componentWillReceiveProps中分别设置图像状态,即:

if (nextProps.selected) {
    // If the nextProps.selected props id equals the this event id then selected else non-selected.
    if (nextProps.selected.id === nextProps.event.id) {
        console.log('SELECTED: ' + JSON.stringify(nextProps.selected));
        // set staae to active
        this.setState({
            active: true,
            image: this.markerIcon(nextProps.event.interest[0], true)
        });
        console.log(interestIconsSelected[nextProps.event.interest[0]]);
    } else {
        // set state to not active
        console.log('NON-SELECTED: ' + JSON.stringify(nextProps.event));   
        this.setState({
            active: false,
            image: this.markerIcon(nextProps.event.interest[0], false)
        });                
    }
}

renderIcon() {
    if (this.props.event.type === 'Event') {
        return (
            <Image
                source={this.state.image}
                style={Styles.MapMarker.eventImage}
            />
        )
    }
}

改变图片状态似乎更有效,因为图像会立即改变,但似乎初始呈现的图像根本没有设置,因此直到选择之前它将是一个空图标。非常感谢,感激任何帮助。
更新:尝试在MapView.Marker下定义Image组件,但这并不起作用。
this.state.markers
.map(e =>
    <MapView.Marker
        key={e.id}
        onPress={() => this.handleLocationPush(e)}
        coordinate={e.location}
    >
        {/* <MapMarker
            event={e}
            size={this.state.markerSize}
        /> */}
        <Image
            source={this.state.selectedEvent === e ? interestIconsSelected[e.interest[0]] : interestIcons[e.interest[0]]}
            style={Styles.MapMarker.eventImage}
        />
    </MapView.Marker>
)

但是这个方法可以工作,尽管你似乎不能对MapView.Marker应用样式,但这不是我想要的实现方式,因为我想保留自定义的MapMarker组件。
this.state.markers
.map(e =>
    <MapView.Marker
        key={e.id}
        onPress={() => this.handleLocationPush(e)}
        coordinate={e.location}
        image={this.state.selectedEvent === e ? interestIconsSelected[e.interest[0]] : interestIcons[e.interest[0]]}
    />
)

上述两个代码片段,无论是直接在MapView.Marker上使用图像属性还是在MapView.Marker下直接使用Image组件,都不如使用MapMarker子组件好。

1个回答

1
您使用了componentWillReceiveProps生命周期方法,它不会在第一次渲染时运行。同时,在constructor状态中使用了this.state.initialized,其值为false,这将使您需要点击两次才能使其生效。请注意保留HTML标签。
componentWillReceiveProps(nextProps) { // it did not run at first render
  if (!this.state.initialized) { // this.state.initialized with is false in constructor
    console.log('initialization');            
    this.setState({initialized: true});
  }
  .......
}

如果你这样做,完全可以删除componentWillReceiveProps

markerIcon() { //did not get interest directly instead access it from props
  return this.props.selected.id === this.props.event.id ?
   interestIconsSelected[this.props.event.interest[0]] 
   : 
   interestIcons[this.props.event.interest[0]];
}

在这里,您可以使用相同比较的两个对象进行比较,因为它们是深度的,您可以使用类似于此的内容,以避免Babel混淆:查看更多
<Image
  // use this.state.selectedEvent.id  === e.id instead of this.state.selectedEvent  === e
  source={this.state.selectedEvent.id  === e.id  ? interestIconsSelected[e.interest[0]] : interestIcons[e.interest[0]]}
  style={Styles.MapMarker.eventImage}
 />

我希望这有所帮助。谢谢。


谢谢你的回答Mohamed,请看我的编辑。似乎如果您使用MapView.Marker的image属性,图像会动态更改,但是任何子组件都不会,即使有条件,例如this.props.selected.id === this.props.event.id ? interestIconsSelected[this.props.event.interest[0]] : interestIcons[this.props.event.interest[0]]; - Michael
你能为此创建一个快速的仓库吗?你确定这不是样式问题,比如标记未被按下吗? - Mohamed Khalil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接