2015-11-17 140 views
0

我正在寫天氣應用程序,並希望在horizo​​ntalscrollview中顯示每小時預測。我從我創建的一個天氣類中得到一些json對象/數組的數據,這些數據是使用asynctask調用的。水平滾動視圖具有線性佈局(水平),因爲它只能有一個孩子,然後包含多個具有兩個文本視圖和一個圖像視圖的垂直線性佈局。這樣,單行包含列,每列都有一個小時,溫度和圖標堆疊在一起,所有這些我都想以編程方式設置。一切看起來都很好,並且構建得很好,但是當我在galaxy選項卡上運行應用程序時,只有activity_main.xml佈局似乎被調用,就好像它從不實現我的水平滾動視圖佈局。Android Studio佈局未設置

這裏是我的MainActivity.java的的onCreate():

public class MainActivity extends AppCompatActivity { 

    Context context; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     LinearLayout parentLayout = (LinearLayout) findViewById(R.id.parentLayout); 

     HorizontalScrollView hsv = (HorizontalScrollView) findViewById(R.id.hsvView); 
     LinearLayout linLay = (LinearLayout) findViewById(R.id.linLay); 


     //linlay.setOrientation(LinearLayout.HORIZONTAL); 
     //linlay.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,50dp, LinearLayout.LayoutParams.WRAP_CONTENT)); 
     // hsv.addView(linlay); 

     int viewCount = 10; 

     final LinearLayout[] childLayout = new LinearLayout[viewCount]; 
     final TextView[] hourText = new TextView[viewCount]; 
     final TextView[] tempText = new TextView[viewCount]; 
     final ImageView[] iconView = new ImageView[viewCount]; 


     for(int i = 0; i < viewCount; i++) { 

      childLayout[i] = new LinearLayout(this); 
      childLayout[i].setOrientation(LinearLayout.VERTICAL); 
      //childLayout[i].setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); 

      hourText[i] = new TextView(this); 
      tempText[i] = new TextView(this); 
      iconView[i] = new ImageView(this); 

      childLayout[i].addView(hourText[i]); 
      childLayout[i].addView(tempText[i]); 
      childLayout[i].addView(iconView[i]); 

      linLay.addView(childLayout[i]); 


     } 

     //put into separate class 

     Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 

     final Button button = (Button) findViewById(R.id.button); 
     button.setText("Get Weather"); 



     button.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       //may want to listen for good network connection response first 

       WeatherTask WunWeather = new WeatherTask(context, childLayout,hourText,tempText,iconView, button); 
       WunWeather.execute(); 
      } 


     }); 

    } 

} 

我activity_main.xml中是獲取與每一個項目創建的標準之一。我刪除了浮動操作按鈕,並用@ layout/horizo​​ntal_scroll替換了標準include @ layout/content_main。

這裏是我的horizo​​ntal_scroll.xml佈局:

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

    <Button 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="@+id/button_text" 
     android:id="@+id/button" /> 

    <HorizontalScrollView 
     android:layout_width="fill_parent" 
     android:layout_height="50dp" 
     android:id="@+id/hsvView" > 

     <LinearLayout 
      android:orientation="horizontal" 
      android:layout_width="wrap_content" 
      android:layout_height="match_parent" 
      android:id="@+id/linLay"> 

     </LinearLayout> 
    </HorizontalScrollView> 


</LinearLayout> 

這是我的WeatherTask設置所有從收集的數據,這些意見對於所有這一切都在另一個線程。我知道,JSON數據被正確檢索:

public class WeatherTask extends AsyncTask<Void, Void, Void> { 


    LinearLayout[] child; 
    TextView[] hoursView; 
    String[] hoursData = new String[10]; 
    TextView[] tempsView; 
    String[] tempsData = new String[10]; 
    ImageView[] iconsView; 
    //String[] iconsUrl = new String[10]; 
    Bitmap[] iconsBit = new Bitmap[10]; 

    Button button; 
    Context context; 

    JSONObject json; 
    JSONArray hourly; 

    //Bitmap icon = null; 

    String AM_PM = ""; 

    /* 
    WeatherTast(Textview[] text, ImageView[] icons, Button button) { 

    } 
    */ 
    WeatherTask(Context context, LinearLayout[] child, TextView[] hours, TextView[] temps, ImageView[] icons, Button button) { 
     this.context = context; 
     this.child = child; 
     this.hoursView = hours; 
     this.tempsView = temps; 
     this.iconsView = icons; 
     this.button = button; 
    } 

    //after onpreexecute() method 
    //passes result to onpostexecute() 
    @Override 
    protected Void doInBackground(Void... params) { 
     Log.d("AsyncTask","got to doInBackground"); 
     //goes to onpostexecute() 
     //need eventually call on gps class to get lat/lon from here 
     GetWeather weather = new GetWeather(40.693,-89.590); 
     json = weather.jsonWeather(); //organized by hour 
     Log.d("AsyncTask", String.valueOf(json)); 
     //send json up to database 

     try { 
      //hourly = json.getJSONArray("Hourly Forecast"); 
      for(int i=0; i<10; i++) { 
       JSONObject tempHour = json.getJSONArray("Hourly Forecast").getJSONObject(i); 
       hoursData[i] = tempHour.getString("Hour"); //get hour 
       tempsData[i] = tempHour.getString("Hour Temp"); 

       iconsBit[i] = null; 
       InputStream in = new URL(tempHour.getString("Icon")).openStream(); 
       iconsBit[i] = BitmapFactory.decodeStream(in); 
       //may want to save all images locally 
      } 



     } catch(Exception e) { 

     } 
     Calendar time = Calendar.getInstance(); 
     int minutes = time.get(Calendar.MINUTE); 
     int hours = time.get(Calendar.HOUR); 

     if (time.get(Calendar.AM_PM) == 1) { 
      AM_PM = "PM"; 
     } else {AM_PM = "AM";} 
     //Integer hour = currentTime.HOUR; 
     //Integer min = currentTime.MINUTE; 

     return null; 
    } 
    //first method called in asynctask with .execute() in main ui thread 
    @Override 
    protected void onPreExecute() { 
     //may not want to clear out latest data just in case a network connection exception is thrown 
     button.setText("Getting weather"); 
     Log.d("AsyncTask", "got to preexecute"); 
     // textView.setText(""); 
     //imageView.setImageBitmap(null); 

     //return s; 
    } 

    //after finishing job, publishes result to UI thread 
    @Override 
    protected void onPostExecute(Void v) { 
     //super.onPostExecute(j); 
     //button says "weather updated @timestamp 
     //imageView downloads icon image last 
     //textView shows current temp 
     Log.d("AsyncTask","got to onpostExecute"); 

     try { 
      //j.getString("Temperature"); 
      Calendar time = Calendar.getInstance(); 

      for (int i = 0; i < 10; i++) { 

       hoursView[i].setText(hoursData[i]); 
       tempsView[i].setText("Temperature: " + tempsData[i] + "\u2109"); 
       iconsView[i].setImageBitmap(iconsBit[i]); 
      } 
      button.setText("Weather Updated at " + time.get(Calendar.HOUR) + ":" + time.get(Calendar.MINUTE) 
        + " " + AM_PM); 

     } catch(Exception e) { 

     } 

    } 

} 

正如你所知道的,我是很新的應用程序。我的logcat沒有任何錯誤,但是我的WeatherTask中沒有任何log.d語句正在顯示。謝謝你的幫助。我在Windows x64上使用API​​ 23。

回答

1

問題出在這樣的事實,即你在開始時並沒有佈局中的內容,並且提供的佈局參數(如wrap_content)依賴內容來正確調整視圖的大小。視圖將在用戶點擊按鈕之前顯示(因爲按鈕本身就是一個視圖)。

顯示視圖的第一階段是測量。此時,測量過程將爲每個空白線性佈局(或大小爲0的兒童),空白文本視圖和設置爲wrap_content的空白圖像視圖分配寬度和高度= 0,並且整個佈局變得不可見。你可以閱讀更多關於顯示視圖here

當您稍後填寫文本視圖和圖像視圖時,它們已被顯示,並且由於它們的大小爲0,因此實際上看不到內容。要從頭開始重新繪製視圖,您需要調用requestLayout(),然後android應測量它們,設置佈局並最終繪製視圖。爲了實現這一目標,在onPostExecute()結束時,您可以添加以下代碼:

LinearLayout parentLayout = context.findViewById(R.id.parentLayout); 
parentLayout.requestLayout(); 

這應該更新的觀點和正確地顯示它們。

請注意,我們不會撥打invalidate()來代替,因爲它只是完成最後一步 - 繪製視圖。

您可能希望在創建活動時包含數據,因此用戶從不會看到空白區域,但如果這樣做,請注意,由於測量可能會在完成之前發生,並且您將再次使用requestLayout()

+0

我認爲這可能與此有關。我把你的兩行無濟於事。我的asynctask中的logcat標籤甚至沒有出現在logcat中,就好像我的應用程序甚至沒有使它那麼遠。我需要在我的MainActivity中使用requestLayout()嗎?我還需要爲我的每個視圖和佈局執行requestLayout嗎? –