BaseAdapter for Spinnerから継承されたCustomAdapterをAndroidデータバインディングするにはどうすればよいですか?

ミンスキー

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つの惑星が表示されません。

最初の惑星が2回リストされた左側のドロップダウンリスト。 期待通りです。

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]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ