web-dev-qa-db-ja.com

OnClickListenerがGridViewの最初のアイテムに対して機能しない

GridViewベースのカレンダーの作成に問題があります。これがグリッドです:

GridView Calendar

これはイベントが入力されたカレンダーであると想定されているため、アダプターにOnClickListenerを実装させ、カレンダーのすべてのボタンにそのリスナーを設定します。すべてのボタンに対して完全に機能します[〜#〜] except [〜#〜]最初のボタン(この場合は番号30)。クリックしても機能しませんが、最初のボタンをクリックしようとした後で別のボタンをクリックすると、他のボタンのクリックを実行する直前に、最初のボタンのクリックが実行されます。

関連する質問を約10ページスキャンしましたが、この問題を抱えている人は見つかりませんでした。助けてください!

尋ねられたように、これが私のコードのgetView関数です:

    public View getView(int position, View convertView, ViewGroup parent)
    {
        View row = convertView;
        ViewHolder holder;
        if (row == null)
        {
            holder = new ViewHolder();
            LayoutInflater inflater = (LayoutInflater) _context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.calendar_day_gridcell, parent, false);
            holder.gridCell = (Button) row.findViewById(R.id.calendar_day_gridcell);
            holder.multiDayEvent = (EventLengthView)row.findViewById(R.id.eventLengthView);
        }
        else{
            holder = (ViewHolder)row.getTag();
        }

        int calendarGridHeight = (calendarView.getHeight()-5)/(getCount()/7);
        AbsListView.LayoutParams params = new AbsListView.LayoutParams(
                Android.view.ViewGroup.LayoutParams.FILL_PARENT,
                calendarGridHeight);
        row.setLayoutParams(params);

        //Change the background drawable depending on the position in the calendar
        if ((position+1) % 7 == 0){
            holder.gridCell.setBackgroundDrawable(getResources().getDrawable(R.drawable.calendar_button_selector_end_row));
        }
        if (getCount() - position < 8){
            holder.gridCell.setBackgroundDrawable(getResources().getDrawable(R.drawable.calendar_button_selector_end_column));
        }
        if (position == getCount()-1){
            holder.gridCell.setBackgroundDrawable(getResources().getDrawable(R.drawable.calendar_button_selector_end));
        }
        holder.gridCell.setOnClickListener(this);

        holder.gridCell.setTag(null);//clear tags

        // ACCOUNT FOR SPACING
        String[] day_color = list.get(position).split("-");
        int theday = Integer.parseInt(day_color[0]);
        int themonth = Integer.parseInt(day_color[2]);
        int theyear = Integer.parseInt(day_color[3]);
        String date = DateFormat.format("dd/M/yy", new Date(theyear,themonth,theday)).toString();
        if ((!eventsMap.isEmpty()) && (eventsMap != null))
        {
            if (eventsMap.containsKey(date))
            {
                holder.multiDayEvent.SetMeasure(calendarView.getWidth()/7, calendarGridHeight);

                holder.multiDayEvent.setVisibility(View.VISIBLE);
                //holder.singleDayEvent.setVisibility(View.VISIBLE);
                Event event = (Event) eventsMap.get(date);
                holder.multiDayEvent.AddEvent(event);
                holder.gridCell.setTag(event);
            }
            else{
                //holder.singleDayEvent.setVisibility(View.GONE);
                holder.multiDayEvent.setVisibility(View.GONE);
            }
        }

        // Set the Day GridCell
        holder.gridCell.setText(Integer.toString(theday));

        if (day_color[1].equals("GREY"))
        {
            holder.gridCell.setTextColor(Color.GRAY);
        }
        if (day_color[1].equals("WHITE"))
        {
            holder.gridCell.setTextColor(Color.WHITE);
        }
        if (day_color[1].equals("BLUE"))
        {
            holder.gridCell.setTextColor(Color.BLUE);
        }

        row.setTag(holder);
        return row;
    }

    public class ViewHolder{
        Button gridCell;
        ImageView singleDayEvent;
        EventLengthView multiDayEvent;
    }

    public void onClick(View view)
    {
        if (view.getTag() != null){
            Event event = (Event)view.getTag();

            eventListView.setAdapter(new EventListAdapter(CalendarScreen.this, event));
            eventListViewLayout.setVisibility(View.VISIBLE);
            eventListViewLayout.startAnimation(fadeIn);
        }
        else if (eventListViewLayout.getVisibility() == View.VISIBLE){
            onBackPressed();
        }
    }

OnClickは、左上隅の最初のグリッドセルを除くすべてのグリッドセルに対して呼び出されます

21
Valentin

わかりました、私は解決策を見つけました。問題はこれらの行でした:

ViewHolder holder;
if (convertView == null)
{
    holder = new ViewHolder();
    LayoutInflater inflater = (LayoutInflater) _context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    convertView = inflater.inflate(R.layout.calendar_day_gridcell, parent, false);
    holder.gridCell = (Button) convertView.findViewById(R.id.calendar_day_gridcell_button);
    holder.multiDayEvent = (EventLengthView) convertView.findViewById(R.id.eventLengthView);
    convertView.setTag(holder);
}
else {
    holder = (ViewHolder) convertView.getTag();
}

そこにgridCellボタンを挿入すると、どういうわけか、アダプターの最初の位置のクリックリスナーが混同されます。タグで取得するのではなく、パスごとにホルダーを示すだけで修正することになりました(これはパフォーマンスには優れていますが、まあまあです)。助けてくれてありがとう。

8
Rory Kelly

同じ問題がありました.if(view == null)句内にsetLayoutParamsを保持することはうまくいきました。そのようにビューのリサイクルを犠牲にする必要はありません。

お気に入り :

 if(row == null){
   // inflate row
   row.setLayoutParams(params);
   //remaining code
 }else{
    holder = (ViewHolder)row.getTag();
 }
 // everything else

なぜそれが機能するのかわかりませんが、私にとってはうまくいきました。また、stackoverflowの同じ問題に関するすべてのコードで、if句の外でsetLayoutParamsが使用されていることにも気づきました。初めてなので、どこにでも投稿できるかわかりません。それが役に立ったことを願っています。

出典:多くの証跡とエラー。

14
BruceWayne

アダプタークラスではなく、。setAdapter()メソッドの後のアクティビティでOnClickListener()を使用します。

gridView.setAdapter(adapter);
gridView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id) {
    Toast.makeText(GridViewActivity.this, "" + position,
             Toast.LENGTH_SHORT).show();
    }
});
8
Rashid

私はこれと同じ問題を抱えていました。最初のアイテムのクリックイベントが大幅に遅れました。私はすでにnotifyDataSetInvalidated()を使用していました。 onItemClickListener()を使用すると問題が解決しました、ただし、個々のアイテムのonClickリスナーがこの動作をする理由はまだわかりません。

1
danp

価値があるので、私もこの問題を抱えていました(グリッドビューの最初のセルがonclickを遅らせました)。

私の場合、(少しカスタマイズされた)グリッドビューと動的なイメージビューのセットを使用していて、グリッドビューを表示/削除して再描画しました。事前に準備され、アダプタに保存されているすべてのイメージビュー。

最初は、アダプターでnotifyDataSetChanged()を使用しましたが、これにより、セットが更新されるたびに最初のセルのクリックが遅延する問題が発生しました。グリッドビューを無効にするように変更しましたが、問題はありません。私のすべてのビューはすでに作成されてアダプタに保存されていることに注意してください。これは、実際に表示されているビューをチェックするgetviewメソッドにすぎません。

1
pgrav

各ボタンにonClickListenersを設定する代わりに、GridViewオブジェクトにonItemClickListenerを設定します。

そして、私はあなたの問題について別の質問を見つけました ここ 。たぶんバウンティ?

0
cosmincalistru

これを参照してください link 、グリッドビューの背景色をTRANSPARENTに設定しています。それはあなたを助けるかもしれません。

0
Archa

何日も費やした後、次のようにレイアウトパラメータを設定します。

if (view == null) {

        // call the user's implementation
        view = mInflater.inflate(mViewId, null);
        holder = createHolder(view);
        // we set the holder as tag
        view.setTag(holder);

        rlMainCell = (RelativeLayout)view.findViewById(R.id.rlMainCell);
        rlMainCell.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) view.getResources().getDimension(R.dimen._128sdp)));

    } else {
        // get holder back...much faster than inflate
        holder = (ViewHolder) view.getTag();
    }

それは私には絶対にうまくいきます

0
Shweta Bhagat