簡體   English   中英

如何從 View.gone 恢復視圖。 在 xml 中使用 'android:visibility="gone"' 后 setVisibility(View.VISIBLE) 不工作

[英]How to recover view from View.gone. setVisibility(View.VISIBLE) not working after using 'android:visibility="gone"' in xml

我的問題:在我的 xml 文件中,我在標記為 assess_layout_list 的線性布局中定義了 android:visibility="gone"。 然后,在 course_adapter_layout 的 onClick() 中,整個視圖,我將可見性設置回 View.VISIBLE,這不起作用,即使在它工作之前的 Log 調用,調用 assess_list_layout 的 LinearLayout object 不是 null,它當我在 xml 文件中定義 visibility="invisible" 時確實有效。 不過,我希望它一開始就消失,並在點擊后可見,因為這符合應用程序的設計。

這是我的 course_adapter_view.xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/course_adapter_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:gravity="left"
    >

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="20dp"
        android:layout_marginTop="20dp"
        android:padding="15dp"
        android:elevation="2dp"
        android:background="@drawable/course_header_background">

        <ImageView
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:src="@drawable/course_color_circle"/>

        <Space
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.25"/>

        <TextView
            android:id="@+id/course_adapter_course_code"
            android:text="TextView1"
            android:layout_width="wrap_content"
            android:layout_height="20dp"
            android:layout_weight="0.5"/>

        <Space
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.25"/>


        <TextView
            android:id="@+id/course_adapter_course_title"
            android:text="TextView2"
            android:layout_width="wrap_content"
            android:layout_height="20dp"/>

    </LinearLayout>

    <LinearLayout
        android:id="@+id/assess_list_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_marginRight="40dp"
        android:layout_marginLeft="40dp"
        android:background="@drawable/course_body_background"
        android:padding="20dp"
        android:visibility="gone"
        >


        <ListView
            android:id="@+id/course_adapter_assess_list"
            android:layout_width="match_parent"
            android:layout_height="250dp"
            android:layout_marginBottom="10dp"/>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="left"
                android:text="More" />

            <Space
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"/>
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="left"
                android:text="New"/>

        </LinearLayout>


    </LinearLayout>


</LinearLayout>

這是我的 CourseListAdapter.java 文件,我用它來為課程列表中的每門課程創建每個視圖,減去通常的東西:

package com.example.schoolplanner2.adapters;


public class CourseListAdapter extends ArrayAdapter<Course> {
  private static final String TAG = "CourseListAdapter";

  private Context context;
  int mResource;

  public CourseListAdapter(@NonNull Context context, int resource, @NonNull ArrayList<Course> objects) {
    super(context, resource, objects);
    this.context = context;
    mResource = resource;
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
    // get info
    String course_code = getItem(position).getCourseCode();
    Double course_grade = getItem(position).getCurrentGrade();

    // make inflater and inflate the layout
    LayoutInflater inflater = LayoutInflater.from(context);
    View v = inflater.inflate(mResource, parent, false);


    TextView tv_course_code = v.findViewById(R.id.course_adapter_course_code);
    TextView tv_course_title = v.findViewById(R.id.course_adapter_course_title);

    tv_course_code.setText(course_code);
    tv_course_title.setText(String.valueOf(course_grade));

    // add on click to each list view element
    LinearLayout layout = v.findViewById(R.id.course_adapter_layout);
    layout.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
        Log.i(TAG, "List view element has been clicked " + course_code);

       
        // expand the view to include a new fragment
        LinearLayout assess_list_layout = view.findViewById(R.id.assess_list_layout);
        assess_list_layout.setVisibility(View.VISIBLE);

        // get the list view and add each course to the course view
        ListView assessment_list_view = (ListView) view.findViewById(R.id.course_adapter_assess_list);
        AssessmentListAdapter assessAdapter = new AssessmentListAdapter(getContext(), R.layout.assessment_adapter_view, getItem(position).getAssessmentList(), getItem(position));
        assessment_list_view.setAdapter(assessAdapter);
      }
    });

    return v;
  }
}

如果您需要更多信息,請告訴我。 還將就完成同一件事的其他方法提出建議。 謝謝你的幫助。 〜賽斯。

編輯:當 assess_list_layout.setVisibility(View.VISIBLE) 在 onClick 之外時它確實有效。

進一步編輯:到目前為止我嘗試過的事情無濟於事:

  • 移動我定義 LinearLayout 組件的位置
  • 在父視圖上調用 invalidate()
  • 使用 runOnUiThread()
  • 在我嘗試為 assess_list_layout 查找 ViewById 的行中將視圖更改為 v,它們是同一件事,因此無濟於事。
  • 在 assess_list_layout 上調用 requestLayout()

更新:我現在設法讓 assess_list_layout 部分在單擊 course_adapter_layout 時出現。 現在唯一的問題是視圖不再占用屏幕空間,它只是變成一個可滾動的視圖,可以上下滾動以查看整個視圖。 此外,當我快速滾動時,它會將視圖重置為啟動時的狀態。

您創建的assess_list_layout linearlayout的資源id 錯誤,目前您有

 LinearLayout assess_list_layout = view.findViewById(R.id.assess_list_layout);

其中viewonCLick的視圖,而不是您的父布局。

將其更新為,

 LinearLayout assess_list_layout = v.findViewById(R.id.assess_list_layout);

這里v是您的父布局的視圖

您的assessment_list_view

LinearLayout assess_list_layout = view.findViewById(R.id.assess_list_layout);
assess_list_layout.setVisibility(View.VISIBLE);

保持這個全局而不是它的工作,不需要使用View.VISIBLE,保持變量唯一

不要在your XML,使用它your XML,因為它會混淆。

android:visibility="gone"

注意:如果您將讓元素可見的代碼放入其onClickListener,它將無法訪問(如果它不占用任何屏幕空間,您將無法單擊它)。 你應該在它下面放置一個最小高度的布局,當你的視圖 l 消失時,新的布局外殼變得可見,它應該得到可見的 onClickListener。 這樣,在您的 View 消失后,這個新布局將能夠將其恢復。

1.查看可見性不起作用

可見性不起作用,因為最初未呈現視圖。 刪除 xml 中消失的可見性並在適配器類中完全處理可見性。 在 'assess_list_layout' 中,linerlayout 的高度可以是硬編碼的,因為在這個布局中,listview 的高度已經被硬編碼了。 您可以硬編碼為 300 並檢查。 這種方式將有助於視圖獲得初始渲染。

2.滾動問題

滾動已經可見的 'assess_list_layout' 視圖時可能不可見。 這是因為我們需要處理可見性,這種處理類似於列表視圖中的復選框選擇處理。 希望Course類是模型類,其中添加另一個名為isSelected 的屬性為 boolean 並將默認值設置為false 請參考下面的課程類,

課程班

public class Course {
private boolean isSelected = false;

public boolean isSelected() {
        return isSelected;
    }

    public void setSelected(boolean selected) {
        isSelected = selected;
    }

}

請參考適配器類中的以下代碼更改。

    public class CourseListAdapter extends ArrayAdapter<Course> {
      private static final String TAG = "CourseListAdapter";
    
      private Context context;
      int mResource;
    
      public CourseListAdapter(@NonNull Context context, int resource, @NonNull ArrayList<Course> objects) {
        super(context, resource, objects);
        this.context = context;
        mResource = resource;
        }
    
        @NonNull
        @Override
        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        // get info
        String course_code = getItem(position).getCourseCode();
        Double course_grade = getItem(position).getCurrentGrade();
    
        // make inflater and inflate the layout
        LayoutInflater inflater = LayoutInflater.from(context);
        View v = inflater.inflate(mResource, parent, false);
    
    
        TextView tv_course_code = v.findViewById(R.id.course_adapter_course_code);
        TextView tv_course_title = v.findViewById(R.id.course_adapter_course_title);
    
    //My Change
      // expand the view to include a new fragment
            LinearLayout assess_list_layout = view.findViewById(R.id.assess_list_layout);
    
    // get the list view and add each course to the course view
            ListView assessment_list_view = (ListView) view.findViewById(R.id.course_adapter_assess_list);
    
    assess_list_layout.setVisibility(View.GONE);
    
    if (getItem().get(position).isSelected()) {
    assess_list_layout.setVisibility(View.Visible);
    AssessmentListAdapter assessAdapter = new AssessmentListAdapter(getContext(), R.layout.assessment_adapter_view, getItem(position).getAssessmentList(), getItem(position));
            assessment_list_view.setAdapter(assessAdapter);
    }
//My Change
    
        tv_course_code.setText(course_code);
        tv_course_title.setText(String.valueOf(course_grade));
    
        // add on click to each list view element
        LinearLayout layout = v.findViewById(R.id.course_adapter_layout);
        layout.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View view) {
            Log.i(TAG, "List view element has been clicked " + course_code);
    
           //My Change
            getItem().get(position).setSelected(true);          
            //My Change
            assess_list_layout.setVisibility(View.VISIBLE);

            
            AssessmentListAdapter assessAdapter = new AssessmentListAdapter(getContext(), R.layout.assessment_adapter_view, getItem(position).getAssessmentList(), getItem(position));
            assessment_list_view.setAdapter(assessAdapter);
          }
        });
    
        return v;
      }
    }

我已將其注釋為My Change以查找代碼中的差異。

問題 1

// make inflater and inflate the layout
   LayoutInflater inflater = LayoutInflater.from(context);
   View v = inflater.inflate(mResource, parent, false);

你不重用視圖,導致每次調用 getView() 時都會膨脹一個新視圖;由於 inflate() 方法是 IO 敏感的,它會減慢滾動的平滑度,觸發 jank。

嘗試這個

// make inflater and inflate the layout
        View v = null;
        if (convertView == null) {
            LayoutInflater inflater = LayoutInflater.from(context);
            v= inflater.inflate(mResource, parent, false);
        } else {
            v = convertView;
        }

問題 2

當 scorll listview 時,您需要重置 itemview 狀態,將“expand”屬性添加到您的Course bean,當單擊 item set expand = true 時;然后在 layout.setOnClickListener 上方添加流動代碼

v.findViewById(R.id.assess_list_layout).setVisibility( item.expand ? View.VISIBLE:View.GONE);
ListView assessment_list_view = (ListView) v.findViewById(R.id.course_adapter_assess_list);
if (item.expand) {
    AssessmentListAdapter assessAdapter = new  AssessmentListAdapter(getContext(), R.layout.assessment_adapter_view, 
   item.getAssessmentList(), item);
   assessment_list_view.setAdapter(assessAdapter);
}

問題 3

getView()方法中設置 setOnClickListener ,每次調用 getView() 時都會創建一個新的 Clicker 實例。 改用listView.setOnItemClickListener()

提示:

畢竟,你應該使用 RecyclerView 而不是 ListView,這是一個強大的 UI 小部件

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM