2017-02-06 4 views
1

私は、クロノメーター、テキストビュー、およびスイッチを保持するカスタムセルを持つリストビューを持っています。このリストビューには、ArrayListからのダンビーデータが格納されます。スイッチがクリックされるたびに、それは常に、リストビューの最後の項目に影響します。Android - リストビュー項目のOnClickListenerは最後の行にのみ影響します

は、ここに私のカスタムtimeTrackCellAdapterクラスここ

public class timeTrackCellAdapter extends ArrayAdapter { 
    private final Activity activity; 
    private final List timeParams; 
    TimeView tView = null; 
    View rowView; 
    //Constructor 
    public timeTrackCellAdapter(Activity activity, List objects){ 
     super(activity, R.layout.cell_layout, objects); 
     this.activity = activity; 
     this.timeParams = objects; 
    } 
    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     rowView = convertView; 


     if(rowView == null) 
     { 
      // Get a new instance of the row layout view 
      LayoutInflater inflater = activity.getLayoutInflater(); 
      rowView = inflater.inflate(R.layout.cell_layout, null); 

      // Hold the view objects in an object, 
      // so they don't need to be re-fetched 
      tView = new TimeView(); 
      tView.timer = (Chronometer) rowView.findViewById(R.id.timeTracker); 
      tView.jobText = (TextView) rowView.findViewById(R.id.secondaryRowText); 
      tView.jobSwitch = (Switch) rowView.findViewById(R.id.timeSwitch); 

      // Cache the view objects in the tag, 
      // so they can be re-accessed later 
      rowView.setTag(tView); 
     } else { 
      tView = (TimeView) rowView.getTag(); 
     } 

     // Transfer the job/time from the data object 
     // to the view objects 
     final timeTrackCell currentTime = (timeTrackCell) timeParams.get(position); 

     tView.timer.setBase(currentTime.getChronometerTime()); 
     tView.jobText.setText(currentTime.getJobString()); 
     tView.jobSwitch.setChecked(currentTime.getSwitchPosition()); 


     //OnClick for switch toggle 
     tView.jobSwitch.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 

       Boolean newCheck = tView.jobSwitch.isChecked(); 
       System.out.println(tView.jobText.getText()); 

       //If newCheck returns true, the switch is being turned on 
       //If newCheck returns false, the switch is being turned off 
       tView.timer.stop(); 
       System.out.println(newCheck); 
       if(newCheck){ 

        tView.jobSwitch.setChecked(true); 
        tView.jobText.setText(currentTime.getJobString()); 
        tView.timer.setBase(currentTime.getChronometerTime()); 
        tView.timer.start(); 


       }else{ 

        tView.timer.stop(); 
        tView.jobSwitch.setChecked(false); 
        tView.jobText.setText(currentTime.getJobString()); 
        tView.timer.setBase(currentTime.getChronometerTime()); 

       } 


      } 
     }); 

     return rowView; 

    } 


    protected static class TimeView { 
     protected Chronometer timer; 
     protected TextView jobText; 
     protected Switch jobSwitch; 
    } 
} 

のしている私のtimeTrackCellクラスは、すべての私の取得し、私のアダプタここで

public class timeTrackCell { 
    private boolean switchPosition; 
    private long chronometerTime; 
    private String jobString; 

    public timeTrackCell(boolean switchPosition, long chronometerTime, String jobString){ 
     this.switchPosition = switchPosition; 
     this.chronometerTime = chronometerTime; 
     this.jobString = jobString; 
    } 
    //sets 
    public void setSwitchPosition(boolean switchPosition){ 
     this.switchPosition = switchPosition; 
    } 
    public void setChronometerTime(long chronometerTime){ 
     this.chronometerTime = chronometerTime; 
    } 
    public void setJobString(String jobString){ 
     this.jobString = jobString; 
    } 
    //gets 
    public boolean getSwitchPosition(){ 
     return switchPosition; 
    } 
    public long getChronometerTime(){ 
     return chronometerTime; 
    } 
    public String getJobString(){ 
     return jobString; 
    } 


} 

のためのセットは私の細胞のためのxmlファイルで、cell_layout

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:minHeight="140px" 
    > 
    <!--140px Seems to be the right height for 7 cells per page--> 
    <!-- Block for custom listview items --> 
    <Chronometer 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:id="@+id/timeTracker" 
     android:layout_gravity="left" 
     android:textSize="25sp" 
     android:paddingLeft="10px" 
     android:layout_centerVertical="true"> 
    </Chronometer> 

    <TextView 
     android:id="@+id/secondaryRowText" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:layout_below="@id/timeTracker" 
     android:textSize="15sp" 
     android:paddingLeft="10px" 
     android:paddingTop="30px" 
     > 
    </TextView> 

    <Switch 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:id="@+id/timeSwitch" 
     android:gravity="right" 
     android:layout_centerVertical="true" 
     android:focusable="false" 
     android:clickable="false" 
     > 
    </Switch> 
</RelativeLayout> 

ここでは、listviewを作成してd ata。 timeKeeping.java

public class timeKeeping extends AppCompatActivity { 
    public String empName = "Zach"; 
    private ListView lv; 
    //tempchange 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     ///// 
     //Button that shows who is logged in 
     setContentView(R.layout.activity_time_keeping2); 
     Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
     setSupportActionBar(toolbar); 
     FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 
     fab.setImageResource(R.drawable.ic_temp_profile_image); 
     fab.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       String greetingString = "Welcome back, " + empName + "!"; 
       Snackbar.make(view, greetingString, Snackbar.LENGTH_LONG) 
         .setAction("Action", null).show(); 
      } 
     }); 
     getSupportActionBar().setDisplayHomeAsUpEnabled(true); 
     ///// 
     lv = (ListView) findViewById(R.id.timeList); 
     //DUMBY DATA TO TEST WITH 
     final List timeData = new ArrayList(); 
     Long testData = (long) 1000000; 
     String tempJobTest = "test job "; 
     for(int i = 0; i<5;i++){ 
      String nTempJobTest = tempJobTest + i; 
      timeData.add(new timeTrackCell(false, testData, nTempJobTest)); 

     } 


     lv.setAdapter(new timeTrackCellAdapter(this, timeData)); 

    } 
} 

は、私は私の問題は、私のtimeTrackCellAdapterクラス内で私のonClickであるかなり確信しているが、それがない場合、私はより多くのコードを提供することができます。どんな助力も大いに評価されています!

+2

それはつもりであれば、あなたのために簡単になりますリストビューをrecyclerviewに再フォーマットする、私を信用する – mayosk

答えて

2

onViewには、同じtViewという変数があります。変数はクラススコープであり、メソッドスコープではないためです。 5行を作成すると、最初の行はクラス変数、2行目(最初の行からの参照を失う)などを使用しています。

これは、行をクリックすると最後に追加された行が変更されるためです。

解決策は、メソッドの内部でローカル変数を作成することができます。しかし、私はRecyclerViewを使用することをお勧めします。これはListViewの成功です。とにかく

、最初のクラスから変数を削除します。その後、

public class timeTrackCellAdapter extends ArrayAdapter { 
    private final Activity activity; 
    private final List timeParams; 
    View rowView; 
    .... 

とを、メソッド内に作成します

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    rowView = convertView; 
    TimeView tView; 
+0

tViewをfinalとして宣言しなければ、どうすれば私のsetOnClickListenerの中でそれを参照できますか? – Joris

+0

なぜあなたはそれが最終的になりたいですか?あなたのコードでは最終的に宣言されていません.. – adalPaRi

+0

"変数" tView "内部クラスからアクセスされ、最終的に宣言する必要があるため" – Joris

-2
@Override 
public View getView(int position, View convertView, ViewGroup parent 
{ 
    //OnClick for switch toggle 
    tView.jobSwitch.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 

      Boolean newCheck = tView.jobSwitch.isChecked(); 
      System.out.println(tView.jobText.getText()); 

      //If newCheck returns true, the switch is being turned on 
      //If newCheck returns false, the switch is being turned off 
      tView.timer.stop(); 
      System.out.println(newCheck); 
      if(newCheck){ 

       tView.jobSwitch.setChecked(true); 
       tView.jobText.setText(currentTime.getJobString()); 
       tView.timer.setBase(currentTime.getChronometerTime()); 
       tView.timer.start(); 


      }else{ 

       tView.timer.stop(); 
       tView.jobSwitch.setChecked(false); 
       tView.jobText.setText(currentTime.getJobString()); 
       tView.timer.setBase(currentTime.getChronometerTime()); 

      } 


     } 
    }); 

} 

getViewメソッドでリスナーを設定することは、おそらくアプリにとって最大の失敗です。 getView(int、View、ViewGroup)はスクロールや更新を行うたびに呼び出されるため、おそらくMEMORY-BLACKHOLEを作成することになるので、おそらく宣言したでしょうこの場合、あなたのリスナーは何千回も聞きます。あなたのリスナーを設定するための他のコード断片を試してみてください。これは解決策ではありませんが、厳密な推奨事項です

0

コールnotifyDataSetChanged();

tView.jobSwitch.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 

      Boolean newCheck = tView.jobSwitch.isChecked(); 
      System.out.println(tView.jobText.getText()); 

      //If newCheck returns true, the switch is being turned on 
      //If newCheck returns false, the switch is being turned off 
      tView.timer.stop(); 
      System.out.println(newCheck); 
      if(newCheck){ 

       tView.jobSwitch.setChecked(true); 
       tView.jobText.setText(currentTime.getJobString()); 
       tView.timer.setBase(currentTime.getChronometerTime()); 
       tView.timer.start(); 


      }else{ 

       tView.timer.stop(); 
       tView.jobSwitch.setChecked(false); 
       tView.jobText.setText(currentTime.getJobString()); 
       tView.timer.setBase(currentTime.getChronometerTime()); 

      } 
      //call this method 
      notifyDataSetChanged(); 

     } 
関連する問題