"&&"논리 연산자를 사용한 안드로이드 데이터 바인딩


131

Android 데이터 바인딩을 사용하여 xml에서 및 "&&"연산자를 사용하려고합니다.

android:visibility="@{(bean.currentSpaceId == bean.selectedSpaceId **&&** bean.currentSpaceId > 0)? View.VISIBLE: View.GONE}"

하지만 컴파일 오류가 발생했습니다.

오류 : ': app : dataBindingProcessLayoutsDevDebug'작업에 대한 실행이 실패했습니다. org.xml.sax.SAXParseException; systemId : 파일 : /Users/path/app/build/intermediates/res/merged/dev/debug/layout/fragment_space.xml; lineNumber : 106; columnNumber : 89; 엔티티 이름은 엔티티 참조에서 '&'바로 뒤에 와야합니다.

Android 스튜디오 "이스케이프 처리되지 않은 & 또는 종료되지 않은 문자"의 빨간색 강조 표시 오류.

그래서 어떻게 고쳐야할까요?

편집 : 답을 찾았습니다.이 문자는 이스케이프해야합니다.

'&' --> '&'

'<' --> '&lt;'

'>' --> '&gt;'

레이아웃 xml 파일에서 ">"및 "<"를 사용할 수 있음을 확인했습니다.
Hong

답변:


234

&&로 렌더링되어야합니다 &amp;&amp;.

공식 데이터 바인딩 가이드 에는 이러한 XML 엔터티가 사용되는 비교 연산자의 예가 있습니다.

android:visibility="@{age &lt; 13 ? View.GONE : View.VISIBLE}"

편집하다

답변에서 언급 한 예제 표현은이 답변이 작성된 이후로 영어 버전의 문서에서 사라졌습니다. 그들은 스페인어 버전과 같은 오래된 비 영어 버전의 문서에서 살아남습니다.

어느 쪽이든 XML의 XML 엔티티 사용은 XML의 표준이며 Android 자체와는 아무 관련이 없기 때문에 원래 답변은 여전히 ​​유효합니다.


12
바인딩 표현식에서 도메인 로직을 사용하지 마십시오.이를위한 프리셋 / 컨트롤러가 있습니다.
artkoenig

2
@ ArtjomKönig UI에서 일부 컨트롤을 숨기거나 표시해야한다면 어떨까요? UI 코드를 작성하지
Krusty

3
@Krusty 발표자에서 isMyControlVisible () 메서드를 구현합니다. 여기서 도메인 논리를 사용하여 참 또는 거짓을 반환합니다. 이 메서드에 바인딩하십시오.
artkoenig

1
부울 변수가 너무 많으면이 솔루션이 좋습니다. 그렇지 않으면 코드에 ObservableBoolean.set이 많이있을 것입니다
Lester

@artkoenig 그런 다음 레이아웃을 참조하는 모든 곳에서 추가 부울을 유지해야합니다. 버그의 출처.
Ali Kazi

36

HTML 엔티티 목록

XML에서 & 또는 다른 HTML 엔티티 를 사용할 수 없습니다 . 따라서 이스케이프 문자를 사용해야합니다.

android:text="@{(1==1 &amp;&amp; 2>0) ? `true` : `false`}"

Android에서 자주 사용되는 HTML 문자 엔티티 :

+--------+----------------------------+--+--+--+
| Symbol | Equivalent HTML Entity     |  |  |  |
+--------+----------------------------+--+--+--+
| >      | &gt;                       |  |  |  |
+--------+----------------------------+--+--+--+
| <      | &lt;                       |  |  |  |
+--------+----------------------------+--+--+--+
| "      | &quot;, &ldquo; or &rdquo; |  |  |  |
+--------+----------------------------+--+--+--+
| '      | &apos;, &lsquo; or &rsquo; |  |  |  |
+--------+----------------------------+--+--+--+
| }      | &#125;                     |  |  |  |
+--------+----------------------------+--+--+--+
| &      | &amp;                      |  |  |  |
+--------+----------------------------+--+--+--+
| space  | &#160;                     |  |  |  |
+--------+----------------------------+--+--+--+

다음 은 HTML 엔티티의 전체 목록입니다.


17

레이아웃 마크 업에서 &&를 이스케이프하는 것은 매우 좋지 않은 솔루션입니다. (view) model 개체에 메서드를 만드는 것이 좋습니다.

android:visibility="@{user.adult ? View.VISIBLE : View.GONE}"

public boolean isAdult() {
    return age >= 18;
}

4
이것은 좋은 솔루션이지만, 불행히도 변수 값이 변경되고 (notifyPropertyChanged) 가시성이 업데이트되지 않을 때 호출되지 않습니다.
Bernd Kampl

2
@BerndKampl 사용ObservableBoolean isAdult
S1ngoooor

작동하지 않고 한 번만 호출됩니다!
CodingTT

@BerndKampl 그것을 사용하는 방법, 그것은 여전히 ​​한 번 호출됩니다
CodingTT

@CodingTT가 내 답변을 보면 어딘가에서 업데이트하려면 notifyPropertyChanged 호출이 필요합니다.
Bernd Kampl

3

이 문제를 해결할 수있는 최선의 해결책은 새로운 Bindable 메서드를 도입하는 것이 었습니다.

전에:

item_recyclerview.xml:

<EditText
...
android:enabled="@{myViewModel.myDataModelClass.lastAddedItem &amp;&amp; !myViewModel.myDataModelClass.editTextDisabled}"
/>

MyDataModelClass: (내 viewmodel에서 개최 중)

...
private boolean lastAddedItem;
private boolean editTextDisabled;
...
@Bindable
public boolean isLastAddedItem() {
    return lastAddedItem;
}
public void setLastAddedItem(boolean lastAddedItem) {
    this.lastAddeditem = lastAddedItem;
    notifyPropertyChanged(BR.lastAddedItem);
}
@Bindable
public boolean isEditTextDisabled() {
    return editTextDisabled;
}
public void setEditTextDisabled(boolean editTextDisabled) {
    this.editTextDisabled = editTextDisabled;
    notifyPropertyChanged(BR.editTextDisabled);
}

후:

item_recyclerview.xml:

<EditText
...
android:enabled="@{myViewModel.myDataModelClass.enableEditing}"
/>

MyDataModelClass: (내 viewmodel에서 개최 중)

...
private boolean lastAddedItem;
private boolean editTextDisabled;
...
@Bindable
public boolean isLastAddedItem() {
    return lastAddedItem;
}
public void setLastAddedItem(boolean lastAddedItem) {
    this.lastAddeditem = lastAddedItem;
    notifyPropertyChanged(BR.lastAddedItem);
    notifyPropertyChanged(BR.isEnableEditing);
}
@Bindable
public boolean isEditTextDisabled() {
    return editTextDisabled;
}
public void setEditTextDisabled(boolean editTextDisabled) {
    this.editTextDisabled = editTextDisabled;
    notifyPropertyChanged(BR.editTextDisabled);
    notifyPropertyChanged(BR.isEnableEditing);
}
@Bindable
public boolean isEnableEditing() {
    return isLastAddedItem() && !isEditTextDisabled();
}

해당 코드는 BaseObservable 클래스를 사용하고 있으며 BR은 생성 된 바인딩 클래스입니다. 자세한 설명은이 게시물을 참조하십시오. medium.com/@jencisov/…
Bernd Kampl
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.