BaseAdapterでAndroidDataBindingを使用してスピナーのCustomAdapterを実装する際に問題が発生しました。
データには2つの値があります。2つのTextViewを使用したいと思います。CustomAdapterはBaseAdapterから継承する必要があり、ArrayAdapterを使用したより単純なバリアントは1つのTextViewのみをサポートします。長期的には、2番目のTextViewはImageViewである可能性があるため、2つの値を1つの文字列にマージしてArrayAdapterを使用できるようにすることはまだ役に立ちません。
私も試しました:アイデアとスピナーが正常に機能することを確認するために、DataBindingなしのバージョンを実装しました。データバインディングの実装は、https://github.com/chrislizh/SpinnerTwoWayDataBindingDemoにあるchrislizhのプロジェクトに基づいています。ArrayAdapter。またbinding.executePendingBindings()
、:を呼び出そうとし、ViewHolderパターンを使用しないようにしました。
問題の詳細は次のとおりです。プロジェクトは惑星に関するものです。スピナーは惑星の選択を可能にします。各惑星には名前と距離があります。両方の値が表示されます。PlanetAdapterと呼ばれるCustomAdapterをDataBindingで実装した結果、選択後に最初の項目が2回表示されます。スクリーンショットを参照してください。最初のアイテム以外の惑星を選択すると、その位置が選択内容に切り替わり、2回表示され続けます。このようにして、表示されるリストに常に1つの惑星が表示されません。
PlanetAdapterのコードと、MainActivtyのonCreateメソッドでそれを作成するための呼び出し:
PlanetAdapter
public class PlanetAdapter extends BaseAdapter
{
private int itemLayoutResourceId;
private final List<Planet> planets;
private LayoutInflater inflater;
public PlanetAdapter(@NonNull Context context, @LayoutRes int itemLayoutResourceId, List<Planet> planets)
{
inflater = LayoutInflater.from(context);
this.itemLayoutResourceId = itemLayoutResourceId;
this.planets = planets;
}
@Override
public int getCount()
{
return planets.size();
}
@Override
public Object getItem(int position)
{
return planets.get(position);
}
@Override
public long getItemId(int position)
{
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
PlanetViewHolder holder;
if (convertView == null) {
PlanetSpinnerItemBinding itemBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.planet_spinner_item, parent, false);
itemBinding.setPlanet(planets.get(position));
holder = new PlanetViewHolder(itemBinding);
holder.view = itemBinding.getRoot();
holder.view.setTag(holder);
}
else {
holder = (PlanetViewHolder) convertView.getTag();
}
return holder.view;
}
private static class PlanetViewHolder
{
private View view;
PlanetViewHolder(PlanetSpinnerItemBinding binding)
{
this.view = binding.getRoot();
}
}}
アダプターの作成と設定:
public class MainActivity extends AppCompatActivity implements IDataChangeListener
{
private static final String BUNDLE_SELECTED_PLANET = "bundle_selected_planet";
private ActivityMainBinding activityMainBinding_;
private List<Planet> planets_;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
activityMainBinding_ = DataBindingUtil.setContentView(this, R.layout.activity_main);
planets_ = loadPlanets(this, R.array.planetsInSolarSystem);
if (planets_ != null) {
planets_.add(0, new Planet("", 0)); // insert a blank item on the top of the list
PlanetAdapter planetAdapter = new PlanetAdapter(this, R.layout.planet_spinner_item, planets_);
activityMainBinding_.setSpinAdapterPlanet(planetAdapter);
Planet selectedPlanet = savedInstanceState != null ? savedInstanceState.<Planet>getParcelable(BUNDLE_SELECTED_PLANET) : planets_.get(3);//initial selected planet is Earth, 3 is the index of Earth after a blank item inserted
activityMainBinding_.setBindingPlanet(new BindingPlanet(this, selectedPlanet));
}
} // loadPlanets skipped.
}
惑星クラス:
public class Planet implements Parcelable {
private String name_;
private float distance_; //distance to Sun in AU(Astronomical Unit)
public Planet(String name, float distance) {
name_ = name;
distance_ = distance;
}
protected Planet(Parcel in) {
name_ = in.readString();
distance_ = in.readFloat();
}
public static final Creator<Planet> CREATOR = new Creator<Planet>() {
@Override
public Planet createFromParcel(Parcel in) {
return new Planet(in);
}
@Override
public Planet[] newArray(int size) {
return new Planet[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name_);
dest.writeFloat(distance_);
}
@Override
public String toString() {
return name_ != null ? name_ : super.toString();
}
public String getName() {
return name_;
}
public void setName(String name) {
name_ = name;
}
public float getDistance() {
return distance_;
}
public void setDistance(float distance) {
distance_ = distance;
}
}
アイテムレイアウトのXML:spinner_planet_item.xml `
<data>
<variable
name="planet"
type="au.com.chrisli.spinnertwowaydatabindingdemo.Planet">
</variable>
</data>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/planetName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{planet.name}"
tools:text="Dummy Planet"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"/>
<TextView
android:id="@+id/planetDistance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="8dp"
android:text="@{String.valueOf(planet.distance)}"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
tools:text="2393.0 km"/>
</LinearLayout>
githubコードでは、ファイルの最後にあるクラスPlanetAdapterに(データバインディングなしの)古典的なケースも含めましたが、コメントアウトしました。それが機能することを確認したい場合は、getViewとPlaneViewHolderの実装をそこで切り替えてください。
完全に変更されたプロジェクトは、私のgithubのhttps://github.com/Minsky/SO_Question_SpinnerDataBindingBaseAdapterにあります。
BaseAdapterのBinding実装の何が問題になっていますか?
Commonswareが彼のコメントに書いたように、リサイクルケースのビューをバインドすることはありませんでした。PlanetAdapterのメソッドgetView()の作業コードは、次のようになります。
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
PlanetViewHolder holder;
if (convertView == null) {
PlanetSpinnerItemBinding itemBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.planet_spinner_item, parent, false);
holder = new PlanetViewHolder(itemBinding);
holder.view = itemBinding.getRoot();
holder.view.setTag(holder);
}
else {
holder = (PlanetViewHolder) convertView.getTag();
}
holder.binding.setPlanet(planets.get(position));
return holder.view;
}
そして、PlanetViewHolderは現在バインディングを保持しています:
private static class PlanetViewHolder {
private View view;
private PlanetSpinnerItemBinding binding;
PlanetViewHolder(PlanetSpinnerItemBinding binding) {
this.view = binding.getRoot();
this.binding = binding;
}
}
ブランチ「解決済み」の最終的なGithubプロジェクト:https://github.com/Minsky/SO_Question_SpinnerDataBindingBaseAdapter/tree/solved
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加