마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

ListView 이벤트 관련 질문입니다.

0 추천

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    final ViewHolder holder;
    if(convertView == null){
        convertView = mInflater.inflate(R.layout.row_coupon_list, null);
        holder = new ViewHolder();
        holder.rlcontent = (RelativeLayout) convertView.findViewById(R.id.row_coupon_rl_content);
        holder.txtname = (TextView) convertView.findViewById(R.id.row_coupon_tv_name);
        holder.txtenddate = (TextView) convertView.findViewById(R.id.row_coupon_tv_enddt);
        holder.txtstore = (TextView) convertView.findViewById(R.id.row_coupon_tv_store);
        holder.txtdiscount = (TextView) convertView.findViewById(R.id.row_coupon_tv_discount);
        holder.txtuse = (TextView) convertView.findViewById(R.id.row_coupon_tv_use);
        holder.txtuse.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mCouponList.get(position).getBarcode() != null) {
                    Toast.makeText(mContext, "position : " + position, Toast.LENGTH_SHORT).show();
                    holder.txtbarcode.setVisibility(View.VISIBLE);
                    holder.rlcontent.setVisibility(View.GONE);

                }
            }
        });
        holder.ivimage = (ImageView) convertView.findViewById(R.id.row_coupon_iv_image);

        holder.txtbarcode = (TextView) convertView.findViewById(R.id.row_coupon_tv_barcode);

        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.txtname.setText(mCouponList.get(position).getName());
    holder.txtenddate.setText(mCouponList.get(position).getEnd_dt() + "까지");
    holder.txtstore.setText(mCouponList.get(position).getStore_summary());
    if(mCouponList.get(position).getType() == 1) {
        holder.txtdiscount.setText(String.valueOf(mCouponList.get(position).getDiscount()) + "%");
    } else if(mCouponList.get(position).getType() == 2) {
        holder.txtdiscount.setText("-" + String.valueOf(mCouponList.get(position).getDiscount()) + "원");
    }

    if(mCouponList.get(position).getStatus() == 1 || mCouponList.get(position).getStatus() == 2) {
        if(mCouponList.get(position).getBarcode() != null) {
            holder.txtbarcode.setText(mCouponList.get(position).getBarcode().getBarcode());
        }
    }

    return convertView;
}

현재 getView 메소드입니다.

 

holder.txtuse.setOnClickListener

에서 TextView에 클릭 리스너를 달아서 해당하는 position의 레이아웃을 변경해주는 작업을 해주고 있습니다.

 

제가 원하는 것은 해당 position은 저렇게 변경을 해주고 다른 position의 레이아웃은 반대로 GONE, VISIBLE 작업을 해주고 싶은데... 클릭 된 다른 position의 레이아웃을 잡을 아이디어가 있을까요...??

 

layout code)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <RelativeLayout
        android:id="@+id/row_coupon_rl_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/row_coupon_tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:text="test"/>

        <RelativeLayout
            android:id="@+id/row_coupon_rl_date_store"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/row_coupon_tv_name">
            <TextView
                android:id="@+id/row_coupon_tv_enddt"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center_vertical"
                android:text="test"/>
            <TextView
                android:id="@+id/row_coupon_tv_store"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:layout_toRightOf="@+id/row_coupon_tv_enddt"
                android:gravity="center_vertical"
                android:text="test"/>
        </RelativeLayout>

        <TextView
            android:id="@+id/row_coupon_tv_temp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/row_coupon_rl_date_store"
            android:visibility="gone"
            android:text="test"/>

        <TextView
            android:id="@+id/row_coupon_tv_discount"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/row_coupon_tv_temp"
            android:gravity="center_vertical"
            android:text="50"/>

        <TextView
            android:id="@+id/row_coupon_tv_use"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:layout_below="@+id/row_coupon_tv_discount"
            android:gravity="center_vertical"
            android:background="@drawable/button_blue_outline"
            android:text="사용하기"/>

        <ImageView
            android:id="@+id/row_coupon_iv_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/row_coupon_rl_date_store"
            android:src="@drawable/ic_home_coupon"
            android:background="@android:color/transparent"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>


    <TextView
        android:id="@+id/row_coupon_tv_barcode"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:visibility="gone"/>
</RelativeLayout>

 

taejun (7,240 포인트) 님이 2015년 6월 2일 질문
taejun님이 2015년 6월 2일 수정

1개의 답변

+1 추천
 
채택된 답변
정확히 어떤 것을 하려는지 모르겠습니다만

퍼포먼스 문제가 생길 듯 하네요.

아이템들의 레이아웃을 Visible, Gone하는 것보다는

어댑터의 아이템 리스트를 갱신해주는 것이 좋을 것 같습니다.

 

그리고 위 소스에서

홀더에 새로 텍스트뷰가 들어갈 때에만 클릭리스너를 달아주셨는데

그렇게 하면 리스트 뷰 스크롤 시 클릭리스너가 정상 작동 하지 않을겁니다.

if(convertView == null){

...

}else{

...

}이 끝난 다음에 클릭 리스너를 붙이셔야 할 거에요
파닭칡힌 (1,820 포인트) 님이 2015년 6월 2일 답변
taejun님이 2015년 6월 4일 채택됨
답변 감사드립니다. 한번 다시 해보고 궁금한점 있으면 답변달아볼께요!
현재 TextView에 클릭 리스너가 달려있는데
리스트뷰를 갱신 시킬 방법이 있나요??
어댑터의 데이터를 새로운 데이터로 바꾸고
어댑터변수.notifyDataSetChanged()를 호출 해주면 됩니다.
어댑터 클래스 내에서 텍스트뷰 클릭 이벤트가 발생 시에 데이터가 바뀌는데 어떻게 하면 캐치가 가능할까요??

현재 리스트뷰에서 해당 TextView를 클릭 시 레이아웃을 갈아버리는 역할을 만들어놨는데 이러한 기능을 새로운 데이터를 변경으로 하는 작업이 가능할까요??

레이아웃코드 추가했습니당
헉; 저게 어댑터에 넘겨주는 아이템 레이아웃인가요?

텍스트뷰 클릭시 데이터가 꼬이는 것은
위 코드상에서 클릭리스너를 붙이는 방식이 잘 못되서 입니다
처음 답변 드린 것처럼
getView메소드가 불릴 때마다 텍스트 뷰에 클릭리스너를 붙이세요
네 답변 감사드립니다. 그 부분은 수정하였는데요...
혹시 리스트뷰의 해당 position의 TextView 클릭 시 리스트뷰 아이템의 layout을 전환하고 있는데... 해당 포지션은 전환이 됩니다.. 하지만 클릭 시에 다른 포지션들의 아이템의 레이아웃을 건드리고 싶은데 어떻게 방법이 있을까요?ㅠ
흠.. 아이템 자체를 감추고 보이는게 아니라
아이템의 일부 레이아웃만 보이고 감추시겠다는 거죠?
퍼포먼스 문제 없이 코딩하려면 힘 좀 들겠는데요;
레이아웃을 바꾸려는 포지션이 1개인가요? 다수인가요?
현재 클릭 시 RelativeLayout 과 TextView를 VISIBLE, GONE하는 작업을 하고 있습니다. 레이아웃 코드 상에서 가장 위에 있는 RelativeLayout과 제일 마지막에 있는 TextView를 교체하는데요...

바꾸려는 포지션은 해당 클릭 포지션은 TextView를 VISIBLE, RelativeLayout은 GONE을 하고, 나머지는 모두 TextView는 GONE, RelativeLayout은 VISIBLE입니다.

그래서 생각을 해본게 이전 클릭 됬던 position 값을 기억해두고 해보려했는데 코드로 작성해보려다가 막혀있는 상태입니다...ㅠㅠ
으.. 어렵네요.
아이템 리스트의 개수와 위치가 고정되어 있다면
모든 아이템의 뷰홀더를 전부 저장하는 변수나 클래스를 만들어서
클릭된 포지션의 뷰홀더를 제외한 나머지 뷰홀더들을 통해
레이아웃을 고치면 되지 않을까 합니다.
TextView 클릭 시 리스트뷰를 전체를 동일하게
TextView GONE, RelativeLayout VISIBLE로 한 뒤,
해당 포지션만 TextView VISIBLE, RelativeLayout GONE을 수행시킬 방법이 없을까요...?ㅠㅠ
모든 뷰홀더를 담는 클래스나 배열변수를 만들면 될 것같아요.
중복되지 않게 모든 아이템의 뷰홀더를 담고
for문 돌려서 전부 gone,visible하고
해당 포지션은 클릭리스너안에서 visible,gone하면 되겠죠
답변감사드려요 ㅎㅎ ArrayList<ViewHolder>를 통해 해결하였습니다. 감사해요~
해결 하셨다니 다행이네요!
퍼포먼스 문제가 발생하지는 않나요?
크게 발생하지는 않는데 지금.... 뭔가 index에 문제가 있네요...ㅠㅠ

@Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        if(convertView == null){
            convertView = mInflater.inflate(R.layout.row_coupon_list, null);
            ViewHolder holder;
            holder = new ViewHolder();

            Log.i("size", String.valueOf(position));
            holder.rlcontent = (RelativeLayout) convertView.findViewById(R.id.row_coupon_rl_content);
            holder.txtname = (TextView) convertView.findViewById(R.id.row_coupon_tv_name);
            holder.txtenddate = (TextView) convertView.findViewById(R.id.row_coupon_tv_enddt);
            holder.txtstore = (TextView) convertView.findViewById(R.id.row_coupon_tv_store);
            holder.txtdiscount = (TextView) convertView.findViewById(R.id.row_coupon_tv_discount);
            holder.txtuse = (TextView) convertView.findViewById(R.id.row_coupon_tv_use);
            holder.ivimage = (ImageView) convertView.findViewById(R.id.row_coupon_iv_image);

            holder.rlbarcode = (RelativeLayout) convertView.findViewById(R.id.row_coupon_rl_barcode);
            holder.ivbarcode = (ImageView) convertView.findViewById(R.id.row_coupon_iv_barcode);
//            holder.txtbarcode = (TextView) convertView.findViewById(R.id.row_coupon_tv_barcode);

            mHolderList.add(holder);

            convertView.setTag(mHolderList.get(position));
        } else {
            Log.i("size2", String.valueOf(position));
            mHolderList.set(position, (ViewHolder) convertView.getTag());
        }

        mHolderList.get(position).txtuse.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("position", String.valueOf(position));
                try {
                    // 해당 포지션의 바코드 정보를 가져온다.
                    Barcode barcode = new CouponUseTask(mContext).execute(mCouponList.get(position).getCoupon_id()).get();

                    // 바코드가 있으면 바코드를 보여줌
                    if (barcode != null) {
                        mCouponList.get(position).setBarcode(barcode);
                        ImageLoader.getInstance().displayImage(mCouponList.get(position).getBarcode().getBarcode_image().getUrl(), mHolderList.get(position).ivbarcode, options);
                        mHolderList.get(position).rlbarcode.setVisibility(View.VISIBLE);
                        mHolderList.get(position).rlcontent.setVisibility(View.GONE);
                    }

                    // 클릭된 포지션 외에 전환
                    for(int i = 0; i < mHolderList.size(); i++) {
                        if(i == position)
                            continue;
                        else {
                            mHolderList.get(i).rlbarcode.setVisibility(View.GONE);
                            mHolderList.get(i).rlcontent.setVisibility(View.VISIBLE);
                        }
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        mHolderList.get(position).txtname.setText(mCouponList.get(position).getName());
        mHolderList.get(position).txtenddate.setText(mCouponList.get(position).getEnd_dt() + "까지");
        mHolderList.get(position).txtstore.setText(mCouponList.get(position).getStore_summary());
        if(mCouponList.get(position).getType() == 1) {
            mHolderList.get(position).txtdiscount.setText(String.valueOf(mCouponList.get(position).getDiscount()) + "%");
        } else if(mCouponList.get(position).getType() == 2) {
            mHolderList.get(position).txtdiscount.setText("-" + String.valueOf(mCouponList.get(position).getDiscount()) + "원");
        }
        if(mCouponList.get(position).getImage() != null)
            ImageLoader.getInstance().displayImage(mCouponList.get(position).getImage().getUrl(), mHolderList.get(position).ivimage, options);

        return convertView;
    }

이게 getView 코드인데... 7번째 아이템(position=6)으로 넘어갈 때,
if(convertView == null) 에 먼저 들어가지 않아서 사이즈가 안맞는 문제가 발생하네요 ㅠㅠ
if(converView == null){
...
}else{
mHolderList.set() <======요거 때문에 인덱스가 꼬이는 것 같아요
요거 지우시고
/////////////////////////
뷰홀더 변수에 convertView.getTag()로 뷰홀더 받아서 사용해야
안 꼬일 듯 하네요
}
음... 어떤식으로 변경해야된다는 말씀이시져...ㅠㅠ?

지금 position=6 일 때, (7번째 아이템이 생성될 때)
if(converView==null)에 들어가지 않아서 생성이 안되서 인덱스가 꼬이는 것 같아요....ㅠㅠ
getView에서 받아오는 position은
실제로 리스트뷰에 보이는 convertView의 순서이기 때문에

taejun님의 실제 아이템 갯수가 100개여도
리스트뷰에 보이는 아이템이 6개면
position은 0~5까지 밖에 받아오지 않아요.
계속 0~5를 돌려가면서 사용하는거에요

그러니
Viewholder holder;
if(convertView==null){
...
}else{
holder = (ViewHolder)convertView.getTag();
}
하시고
밑에서 사용하는
mHolderList.get(position)대신
holder를 사용하셔야 안꼬여요
네... 그렇다면 7번째 아이템이 보일 때는
if(converView==null) 에 들어가서 뷰홀더가 생성이 되어야 되지 않나요...?
말씀대로 아래와 같이 수정하였는데,

@Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        final ViewHolder holder;

        if(convertView == null){
            convertView = mInflater.inflate(R.layout.row_coupon_list, null);

            holder = new ViewHolder();

            Log.i("size", String.valueOf(position));
            holder.rlcontent = (RelativeLayout) convertView.findViewById(R.id.row_coupon_rl_content);
            holder.txtname = (TextView) convertView.findViewById(R.id.row_coupon_tv_name);
            holder.txtenddate = (TextView) convertView.findViewById(R.id.row_coupon_tv_enddt);
            holder.txtstore = (TextView) convertView.findViewById(R.id.row_coupon_tv_store);
            holder.txtdiscount = (TextView) convertView.findViewById(R.id.row_coupon_tv_discount);
            holder.txtuse = (TextView) convertView.findViewById(R.id.row_coupon_tv_use);
            holder.ivimage = (ImageView) convertView.findViewById(R.id.row_coupon_iv_image);

            holder.rlbarcode = (RelativeLayout) convertView.findViewById(R.id.row_coupon_rl_barcode);
            holder.ivbarcode = (ImageView) convertView.findViewById(R.id.row_coupon_iv_barcode);
//            holder.txtbarcode = (TextView) convertView.findViewById(R.id.row_coupon_tv_barcode);

            mHolderList.add(holder);

            convertView.setTag(mHolderList.get(position));
        } else {
            Log.i("size2", String.valueOf(position));
//            mHolderList.set(position, (ViewHolder) convertView.getTag());
            holder = (ViewHolder) convertView.getTag();
        }

        holder.txtuse.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("position", String.valueOf(position));
                try {
                    // 해당 포지션의 바코드 정보를 가져온다.
                    Barcode barcode = new CouponUseTask(mContext).execute(mCouponList.get(position).getCoupon_id()).get();

                    // 바코드가 있으면 바코드를 보여줌
                    if (barcode != null) {
                        mCouponList.get(position).setBarcode(barcode);
                        ImageLoader.getInstance().displayImage(mCouponList.get(position).getBarcode().getBarcode_image().getUrl(), holder.ivbarcode, options);
                        holder.rlbarcode.setVisibility(View.VISIBLE);
                        holder.rlcontent.setVisibility(View.GONE);
                    }

                    // 클릭된 포지션 외에 전환
                    for(int i = 0; i < mHolderList.size(); i++) {
                        if(i == position)
                            continue;
                        else {
                            mHolderList.get(i).rlbarcode.setVisibility(View.GONE);
                            mHolderList.get(i).rlcontent.setVisibility(View.VISIBLE);
                        }
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        holder.txtname.setText(mCouponList.get(position).getName());
        holder.txtenddate.setText(mCouponList.get(position).getEnd_dt() + "까지");
        holder.txtstore.setText(mCouponList.get(position).getStore_summary());
        if(mCouponList.get(position).getType() == 1) {
            holder.txtdiscount.setText(String.valueOf(mCouponList.get(position).getDiscount()) + "%");
        } else if(mCouponList.get(position).getType() == 2) {
            holder.txtdiscount.setText("-" + String.valueOf(mCouponList.get(position).getDiscount()) + "원");
        }
        if(mCouponList.get(position).getImage() != null)
            ImageLoader.getInstance().displayImage(mCouponList.get(position).getImage().getUrl(), holder.ivimage, options);


        return convertView;
    }

처음 리스트뷰를 내릴 시에는 정상적으로 나타납니다... 하지만
getTag가 잘못불리는지... 위로 다시 올라가면 꼬여버리네요...음....
의심가는 부분은
태그 설정할 때 convertView.setTag(mHolderList.get(position));
이거 밖에 없네요..
convertView.setTag(holder)로 해보세요.

그 외에는 저도 모르겠네요..;
...