2015-11-17 88 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吗? –