在 Android 的自定义适配器中设置 Textview 的文本的问题

Posted

技术标签:

【中文标题】在 Android 的自定义适配器中设置 Textview 的文本的问题【英文标题】:Issue in setting Textview's text in Custom Adapter for Android 【发布时间】:2015-01-04 05:11:34 【问题描述】:

我无法在自定义适配器的getView() 方法中设置 textview 的 setText 属性。

我已经尝试了以下解决方案,但它对我不起作用:

Solution One Solution Two Solution Three

Listview.xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/imgLayout"
android:layout_
android:layout_>

<ListView
    android:id="@+id/list"
    android:layout_
    android:layout_
    android:layout_marginTop="40dp"
    android:divider="@null"
    android:dividerHeight="5dp"
    android:scrollbars="none" />

</RelativeLayout>

以下是我的 keep_resing xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/customRowLayout"
android:layout_
android:layout_
android:layout_marginTop="20dp"
android:orientation="horizontal" >

<RelativeLayout
    android:layout_
    android:layout_ >

    <LinearLayout
        android:layout_
        android:layout_
        android:layout_alignParentLeft="true"
        android:orientation="vertical" >

        <ImageButton
            android:id="@+id/Btn"
            android:layout_
            android:layout_
            android:layout_marginLeft="10dp"
            android:background="@drawable/thumb_down_disabled" />

        <TextView
            android:layout_
            android:layout_
            android:gravity="center_horizontal"
            android:text="@string/resing"
            android:textColor="#357EC7"
            android:textSize="10sp" />
    </LinearLayout>

    <LinearLayout
        android:layout_
        android:layout_
        android:layout_centerHorizontal="true"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/lyricsTxt"
            android:layout_
            android:layout_
            android:layout_gravity="center_horizontal" />

        <RelativeLayout
            android:id="@+id/parentLayout"
            android:layout_
            android:layout_
            android:layout_gravity="center"
            android:layout_marginTop="5dp"
            android:background="@drawable/playing_view"
            android:orientation="horizontal" >

            <TextView
                android:id="@+id/helloTxt"
                android:layout_
                android:layout_
                android:layout_centerInParent="true"
                android:layout_marginLeft="5dp"
                android:singleLine="true"
                android:text="Hello"
                android:textColor="#357EC7"
                android:textSize="14sp" />

            <ImageView
                android:layout_
                android:layout_
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginRight="5dp"
                android:background="@drawable/volume" />
        </RelativeLayout>
    </LinearLayout>

    <LinearLayout
        android:layout_
        android:layout_
        android:layout_alignParentRight="true"
        android:orientation="vertical" >

        <ImageButton
            android:id="@+id/keepBtn"
            android:layout_
            android:layout_
            android:layout_marginRight="10dp"
            android:background="@drawable/thumb_up_disabled" />

        <TextView
            android:layout_
            android:layout_
            android:gravity="center_horizontal"
            android:text="@string/keep"
            android:textColor="#357EC7"
            android:textSize="10sp" />
    </LinearLayout>
</RelativeLayout>

下面是我的适配器代码:

import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.simpleframework.xml.stream.Position;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Handler;
import android.os.PowerManager;
import android.sax.StartElementListener;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;


public class KeepReSingAdapter extends BaseAdapter implements OnClickListener 

    /*********** Declare Used Variables *********/
    private Activity activity;
    private ArrayList data;
    private static LayoutInflater inflater = null;
    public Resources res;
    SongCue tempValues = null;
    int i = 0;

    private ArrayList<SongCue> songCue;
    private int cueIndex = 0;
    private String selectedSongId;
    private MediaPlayer mMediaPlayer;
    ViewHolder holder;
    View vi;
    boolean right_button_flag, left_button_flag;
    SessionManager session;

    // int left_button_flag;

    /************* CustomAdapter Constructor *****************/
    public KeepReSingAdapter(Activity a, ArrayList d, Resources resLocal) 

        /********** Take passed values **********/
        activity = a;
        data = d;
        res = resLocal;

        /*********** Layout inflator to call external xml layout () ***********/
        inflater = (LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);



        selectedSongId = SessionManager.getInstance(
                activity.getApplicationContext()).getString(
                AppConstants.SONG_ID);

        right_button_flag = false;
        left_button_flag = false;

        // Session class instance
        session = new SessionManager(activity.getApplicationContext());

    

    /******** What is the size of Passed Arraylist Size ************/
    public int getCount() 

        if (data.size() <= 0)
            return 1;
        return data.size();
    

    public Object getItem(int position) 
        return position;
    

    public long getItemId(int position) 
        return position;
    

    /********* Create a holder Class to contain inflated xml file elements *********/
    public static class ViewHolder 

        public TextView lyricsTxt, helloTxt;
        // public TextView text1;
        public ImageButton leftBtn, rightBtn;
        public RelativeLayout parentLayout;
        public LinearLayout rowLayout;

        // public TextView textWide;
        // ImageView image;

    

    /****** Depends upon data size called for each row , Create each ListView row *****/
    public View getView(final int position, View convertView, ViewGroup parent) 

        vi = convertView;

        if (convertView == null) 

            vi = inflater.inflate(R.layout.keep_resing, null);

            holder = new ViewHolder();
            holder.lyricsTxt = (TextView) vi.findViewById(R.id.lyricsTxt);
            holder.helloTxt = (TextView) vi.findViewById(R.id.helloTxt);

            holder.leftBtn = (ImageButton) vi.findViewById(R.id.reSingBtn);
            holder.rightBtn = (ImageButton) vi.findViewById(R.id.keepBtn);
            holder.parentLayout = (RelativeLayout) vi
                    .findViewById(R.id.parentLayout);
            holder.rowLayout = (LinearLayout) vi
                    .findViewById(R.id.customRowLayout);





            vi.setTag(holder);

         else 
            holder = (ViewHolder) vi.getTag();

        

        if (data.size() <= 0) 



         else 
            /***** Get each Model object from Arraylist ********/
            tempValues = null;
            tempValues = (SongCue) data.get(position);


            holder.lyricsTxt.setText(tempValues.getLyric());

            List<Song> AllSong = SplashScreen_Activity.songs;
            if (selectedSongId != null) 
                for (Song tempsong : AllSong) 
                    if (tempsong.songId.equals(selectedSongId)) 
                        songCue = (ArrayList<SongCue>) tempsong.songCues.songCue;
                    
                
             else 

            




            holder.parentLayout.setOnClickListener(new View.OnClickListener() 

               @Override
               public void onClick(View v) 

                Toast.makeText(activity.getApplicationContext(),
                        " " + position, Toast.LENGTH_SHORT).show();

                     holder.helloTxt.setText("Test");

                    Toast.makeText(activity.getApplicationContext(),
                            holder.helloTxt.getText().toString(),
                            Toast.LENGTH_LONG).show();


                   
               );



        
        vi.setOnClickListener(new OnItemClickListener(position));
        return vi;
    


    @Override
    public void onClick(View v) 
        Log.v("CustomAdapter", "=====Row button clicked=====");

    

    /********* Called when Item click in ListView ************/
    private class OnItemClickListener implements OnClickListener 
        private int mPosition;

        OnItemClickListener(int position) 
            mPosition = position;
        

        @Override
        public void onClick(View arg0) 


        
    


问题是,我无法将文本视图文本更改为“测试”。

注意:如果我通过执行“holder.helloTxt.getText().toString()”看到 Toast 中的值,它会显示“Test”。

我不知道为什么会出现这个问题。任何帮助将不胜感激。

谢谢

【问题讨论】:

你不需要把你的 setOnClickListener 放在外面 if (convertView == null) 吗? 请添加您的列表布局 @LucianoRodríguez :最初只是这样,但那也没有用。 @ChiragJain:列表的布局只是相对布局中的一个简单的ListView。 xml 文件,其中包含 listview 和另一个这是你好可见的? 【参考方案1】:

我终于找到了我的问题的解决方案,并猜猜这是代码中的一个小更新。

我将代码更新为:

final ViewHolder holder; 

CustomAdaptergetView() 内,而不是全局声明。

再次感谢大家的回答。

它帮助我详细研究了我的代码。

【讨论】:

我刚刚接受了 ypur 的回答,但你能解释一下为什么在创建类 final 后,代码可以正常工作。 @SalmanKhan 我遇到了同样的问题,所以我到达了这篇文章。添加“final”解决了我的问题,我知道为什么会这样。 “getView”方法在第一次加载列表视图时调用,或者当您滚动列表视图以使一些新项目出现(消失)在列表视图中时。因此,当您单击它时,不会调用 getView 方法,而是调用 onClick 方法。由于您在getView方法中只设置了持有者对象包含各种项目,所以当您单击它时,持有者对象不包含任何内容。 @SalmanKhan (...没有足够的字符,所以在这里继续) 如果您将持有者声明为最终,当首先调用 getView 时,将创建持有者对象并将其设置为包含 TextView,并且成为最终的。因此,当您稍后单击它时,该持有人仍然包含该 TextView。【参考方案2】:

试试这个希望对你有帮助

    vi = convertView;
    if (vi == null) 
        vi = inflater.inflate(R.layout.xmlfile, null);
        holder = new ViewHolder();
        holder.helloTxt= (TextView) vi.findViewById(R.id.hearTxt);
        holder.parentLayout= (RelativeLayout) vi
                .findViewById(R.id.parentLayout);

        vi.setTag(holder);
    else
        holder=(ViewHolder)vi.getTag();

        holder.parentLayout.setOnClickListener(new View.OnClickListener() 

            @Override
            public void onClick(View v) 

                Toast.makeText(activity.getApplicationContext(),
                        " " + position, Toast.LENGTH_SHORT).show();

                     holder.helloTxt.setText("Test");// not required
                    // just change the value of text in your list(which you are passing to the adapter) at corresponding position and then notify the list
                     notifyDataSetChanged();

                    Toast.makeText(activity.getApplicationContext(),
                            holder.helloTxt.getText().toString(),
                            Toast.LENGTH_LONG).show();


            
        );

       return vi;

它将显示文本“test”,但当您滚动时,它会再次更改为其原始值,因此您还必须更改列表中的值,并将其发送给适配器

在您的情况下,问题还在于,当您更新 TextView 的文本时,它会暂时更新,这就是您在 Toast 中获取 TextView 文本的原因。但是为了在 ListView 中显示更新的文本,您必须通知 List。但是当你这样做时,你的 TextView 会重置为原始值。因此,您所要做的就是获取一个全局 String 变量并将其初始化为您想要的任何初始值

private String yourText="initial text"

并在 getView() 中将 TextView 文本设置为此变量,如下所示

holder.helloTxt.setText(yourText);

当你点击你的 parentLayout 时,只需为这个字符串分配你想要的值并通知列表

yourText="test";
notifyDataSetChanged();

这样就可以了。但是请记住,这仅在您有单行时才有效,如果您有多行,则必须采用 String 数组。

【讨论】:

您是否更改了要传递给适配器的列表中的值? 实际上,我的问题是我有列表项,在里面我有一个包含文本视图的相对布局。现在点击相对布局,我想更改文本视图文本。所以,我的文本将是静态的。 你的意思是说你有单行??如果没有,你是如何膨胀你的行的?将您的整个适配器代码放在清晰的位置以及如何在 Activity 中设置列​​表视图 是的,我有单行。 我在你的 ViewHolder 类中没有找到这个 TextView holder.helloTxt 你也没有在任何地方初始化它??【参考方案3】:

如果convertView not 为空,您是否执行holder = vi.getTag();? 当已经创建视图以将其重新初始化为原来的状态时,这是必要的。

【讨论】:

【参考方案4】:

问题是,我无法将文本视图文本更改为“测试”。

你做错了。假设您的适配器由String 组成。我所期望的是,

 if (convertView == null) 
   // inflate stuff 
   // create older
   // set the older in the converView's tag
   else 
   // retriewholder
  
  // here you set the String in the holder at position:
  String tmpString = getItem(position);
  holder.helloTxt.setText(tmpString);
  holder.parentLayout.setTag(position);

在onClick内部,可以通过标签对象检索位置,更新数据集中的String并调用notifyDataSetChanged

【讨论】:

【参考方案5】:

您的问题是您没有触摸父布局。确保您的手指可以触摸到 parentLayout,您可以为其添加填充。或者你可以试试

holder.helloTxt.setOnClickListener(...)

而不是 parentLayout。

【讨论】:

【参考方案6】:

我见过很多方法,但对我来说最简单的方法是将组件视图传递给适配器。然后,您可以根据需要进行更改。请参阅下面的示例:

Link

【讨论】:

以上是关于在 Android 的自定义适配器中设置 Textview 的文本的问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在 RatingBar 中设置星星的自定义大小

Android - 如何使用适配器类中的代码在布局文件中设置图像?

在android的片段中设置列表视图适配器

BaseAdapter 类不会在 Asynctask 中设置适配器 - Android

android gridview 怎么在适配器中设置不可选择项

android中listvliew中的自定义字体Text-View