尝试显示我的应用程序的天气图标时遇到问题

Having problem trying to display my app's weather icons

这最初是在大约 20 天前被问到的,我试图根据城市的响应(来自 drawable 文件夹)在我的应用程序上显示天气图标 来自天气官方 API 文档 https://openweathermap.org/weather-conditions 中列出的天气状况数量(您始终可以通过查看编辑历史记录来查看)。 API.

有 9 种主要天气状况

这仍然是我的目标:

在 Magdalena Rowicka 的帮助下,我已经取得了一些成就,但即使在尝试自己修复之后问题仍然没有完全解决,这就是为什么我要重新悬赏 post.

我做的第一件事是使用以下数据集创建一个单独的枚举 class:

public enum WeatherIcon {
    Sun, Cloud1, Cloud2, Cloud3, Rain1, Rain2, Thunder, Snow, Mist
}

然后我在片段上声明文本视图的地方添加了这段代码final ImageView imageofWeather = rootView.findViewById(R.id.imageView2);

然后我添加了这个 int drawableResource; // 例如在这里定义默认图标 R.drawable.default_weather_icon 在片段 viewModel.getWeatherDataLiveData().observe(getViewLifecycleOwner(), data -> { 之后。

然后我终于添加了这段代码:

switch (data.getWeather().get(0).getIcon()) { 
                    case WeatherIcon.Sun:
                        drawableResource = R.drawable.sun; //reference to drawable id
                        break;
                    case WeatherIcon.Cloud1:
                        drawableResource = R.drawable.broken_clouds; //reference to drawable id
                        break;
                    case WeatherIcon.Cloud2:
                        drawableResource = R.drawable.few_clouds; //reference to drawable id
                        break;
                    case WeatherIcon.Cloud3:
                        drawableResource = R.drawable.scattered_clouds; //reference to drawable id
                        break;
                    case WeatherIcon.Rain1:
                        drawableResource = R.drawable.small_rain; //reference to drawable id
                        break;
                    case WeatherIcon.Rain2:
                        drawableResource = R.drawable.shower_rain; //reference to drawable id
                        break;
                    case WeatherIcon.Thunder:
                        drawableResource = R.drawable.thunderstorm; //reference to drawable id
                        break;
                    case WeatherIcon.Snow:
                        drawableResource = R.drawable.snow; //reference to drawable id
                        break;
                    case WeatherIcon.Mist:
                        drawableResource = R.drawable.mist; //reference to drawable id
                        break;



        imageofWeather.setImageDrawable(drawableResource);
            }

在 fragment 的 if 语句下直接访问 API 并显示天气图标。 (相应的 9 个图标当前显示在第一个片段的编号行上 class)。

当前设置的问题是:

The value R.drawable.sun(and the rest) assigned to 'drawableResource' is never used.

Required type: Drawable, Provided: int

如果有人能提供帮助,我将不胜感激。

这是我的片段代码:

public class FirstFragment extends Fragment {

    private WeatherDataViewModel viewModel;

    public FirstFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View rootView = inflater.inflate(R.layout.fragment_first, container, false);
        // For displaying weather data
        // all field in Java should be type in camelCase, so not current_temp but currentTemp, not Cloud_out but cloudOut
        // Capitalize name is for class not field
        final TextView current_temp = rootView.findViewById(R.id.textView10);
        final TextView current_output = rootView.findViewById(R.id.textView11);
        final TextView rise_time = rootView.findViewById(R.id.textView25);
        final TextView set_time = rootView.findViewById(R.id.textView26);
        final TextView temp_out = rootView.findViewById(R.id.textView28);
        final TextView Press_out = rootView.findViewById(R.id.textView29);
        final TextView Humid_out = rootView.findViewById(R.id.textView30);
        final TextView Ws_out = rootView.findViewById(R.id.textView33);
        final TextView Visi_out = rootView.findViewById(R.id.textView34);
        final TextView Cloud_out = rootView.findViewById(R.id.textView35);
        final ImageView imageofWeather = rootView.findViewById(R.id.imageView2);


        // Get our ViewModel instance
        viewModel = new ViewModelProvider(this).get(WeatherDataViewModel.class);

        // And whenever the data changes, refresh the UI
        viewModel.getWeatherDataLiveData().observe(getViewLifecycleOwner(), data -> {

            int drawableResource; // here define default icon for example R.drawable.default_weather_icon

            if (data != null) {
                current_temp.setVisibility(View.VISIBLE);
                current_temp.setText(data.getMain().getTemp() + " ℃"); // for that you can use strings resource and templates more in https://developer.android.com/guide/topics/resources/string-resource.html#formatting-strings
                current_output.setVisibility(View.VISIBLE);
                current_output.setText(data.getWeather().get(0).getDescription());
                rise_time.setVisibility(View.VISIBLE);
                rise_time.setText(data.getSys().getSunrise() + " ");
                set_time.setVisibility(View.VISIBLE);
                set_time.setText(data.getSys().getSunset() + " ");
                temp_out.setVisibility(View.VISIBLE);
                temp_out.setText(data.getMain().getTemp() + " ℃");
                Press_out.setVisibility(View.VISIBLE);
                Press_out.setText(data.getMain().getPressure() + " hpa");
                Humid_out.setVisibility(View.VISIBLE);
                Humid_out.setText(data.getMain().getHumidity() + " %");
                Ws_out.setVisibility(View.VISIBLE);
                Ws_out.setText(data.getWind().getSpeed() + " Km/h");
                Visi_out.setVisibility(View.VISIBLE);
                Visi_out.setText(data.getVisibility() + " m");
                Cloud_out.setVisibility(View.VISIBLE);
                Cloud_out.setText(data.getClouds().getAll() + " %");

                // get actual weather.
                switch (data.getWeather().get(0).getIcon()) { //or data.getWeather()[0].getIcon() i don't remember how it work in Java
                    case WeatherIcon.Sun:
                        drawableResource = R.drawable.sun; //reference to drawable id
                        break;
                    case WeatherIcon.Cloud1:
                        drawableResource = R.drawable.broken_clouds; //reference to drawable id
                        break;
                    case WeatherIcon.Cloud2:
                        drawableResource = R.drawable.few_clouds; //reference to drawable id
                        break;
                    case WeatherIcon.Cloud3:
                        drawableResource = R.drawable.scattered_clouds; //reference to drawable id
                        break;
                    case WeatherIcon.Rain1:
                        drawableResource = R.drawable.small_rain; //reference to drawable id
                        break;
                    case WeatherIcon.Rain2:
                        drawableResource = R.drawable.shower_rain; //reference to drawable id
                        break;
                    case WeatherIcon.Thunder:
                        drawableResource = R.drawable.thunderstorm; //reference to drawable id
                        break;
                    case WeatherIcon.Snow:
                        drawableResource = R.drawable.snow; //reference to drawable id
                        break;
                    case WeatherIcon.Mist:
                        drawableResource = R.drawable.mist; //reference to drawable id
                        break;



                    imageofWeather.setImageDrawable(drawableResource);
                }

            } else {
                Log.e("TAG", "No City found");
                current_temp.setVisibility(View.GONE);
                current_output.setVisibility(View.GONE);
                rise_time.setVisibility(View.GONE);
                set_time.setVisibility(View.GONE);
                temp_out.setVisibility(View.GONE);
                Press_out.setVisibility(View.GONE);
                Humid_out.setVisibility(View.GONE);
                Ws_out.setVisibility(View.GONE);
                Visi_out.setVisibility(View.GONE);
                Cloud_out.setVisibility(View.GONE);
                Toast.makeText(requireActivity(), "No City found", Toast.LENGTH_SHORT).show();
            }
        });

        return rootView;
    }

    public void getWeatherData(String name) {
        // The ViewModel controls loading the data, so we just
        // tell it what the new name is - this kicks off loading
        // the data, which will automatically call through to
        // our observe() call when the data load completes
        viewModel.setCityName(name);
    }
}

也许这样试试:

  1. 创建一个天气 class,使用枚举指定要显示的图标。
  2. 下载数据后,转换为创建的class
  3. 一个单独的函数,它将决定为给定的枚举显示什么

已编辑:

public class Example{
  // add to your definition
  private WeaterIcon icon;

  public WeaterIcon getIcon() {
      return icon;
  }

  public void setIcon(WeaterIcon icon) {
      this.icon = icon;
  }
}

enum WeaterIcon {
  SUN, FROG, //type all what want
}

在 onCreateView 中

//there are yor reference to xml object
    final ImageView imageOfWeather = rootView.findViewById(R.id.imageView); // add this reference

并选择正确的图标

int drawableResource; // here define default icon or not
            switch(data.getIcon()) {
                case WeaterIcon.SUN:
                    drawableResource = R.drawable.sun_icon //reference to drawable id
                    break;
                case WeaterIcon.FROG:
                    drawableResource = R.drawable.frog_icon//reference to drawable id
                    break;
                //add all
            }


            imageOfWeather.setImageDrawable(drawableResource);

The line imageofWeather.setImageDrawable(drawableResource); shows this error:

Required type: Drawable, Provided: int

表示setImageDrawable()需要(期望)一个Drawable参数,但是提供(找到)的参数是一个int.

要解决此问题,请改用 setImageResource(),它采用 int 可绘制资源而不是 Drawable

For each case statement, I get the following error:

The value R.drawable.sun(and the rest) assigned to 'drawableResource' is never used.

这是由于先前的错误而引发的,它认为 drawableResource 未被 setImageDrawable() 行使用,因此它警告您您为其分配了一个值但从未使用过它。

应该通过修复第一个警告来修复此警告;虽然,我建议使用私有构造函数重写 enum,该构造函数接收 int 可绘制资源值,它将处理 switch 语句,而不是让片段执行此操作。

新枚举:

public enum WeatherIcon {

    Sun(R.drawable.sun),
    Cloud1(R.drawable.broken_clouds),
    Cloud2(R.drawable.few_clouds),
    Cloud3(R.drawable.scattered_clouds),
    Rain1(R.drawable.small_rain),
    Rain2(R.drawable.shower_rain),
    Thunder(R.drawable.thunderstorm),
    Snow(R.drawable.snow),
    Mist(R.drawable.mist);

    private int drawable;

    WeatherIcon(int drawable) {
        this.drawable = drawable;
    }

    public int getDrawable() {
        return drawable;
    }

}

然后您可以删除它并通过使用枚举的 getDrawable() 方法获取可绘制对象来简化它,而不是片段中的 switch 语句,如下所示:

WeatherIcon icon = data.getWeather().get(0).getIcon();
int drawableResource = icon.getDrawable();
imageofWeather.setImageResource(drawableResource);

您必须在清单文件中创建 activity-alias,根据天气情况设置图标。

<?xml version="1.0" encoding="utf-8"?>
<manifest  xmlns:android="http://schemas.android.com/apk/res/android"
package="io.github.erikjhordanrey.livebinding">

<uses-permission android:name="android.permission.INTERNET" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme"
    android:usesCleartextTraffic="true">

    <activity android:name="io.github.erikjhordanrey.livebinding.view.DcCharacterActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <action android:name="android.intent.action.VIEW" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>


    <activity-alias
        android:name=".MainActivityAlias"
        android:enabled="false"
        android:icon="@drawable/R.drawable.sun"
        android:label="@string/app_name"
        android:roundIcon="@drawable/R.drawable.sun"
        android:targetActivity="io.github.erikjhordanrey.livebinding.view.DcCharacterActivity">

        <intent-filter>

            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />

        </intent-filter>

    </activity-alias>

    <activity-alias
        android:name=".MainActivityAlias"
        android:enabled="false"
        android:icon="@drawable/R.drawable.broken_clouds"
        android:label="@string/app_name"
        android:roundIcon="@drawable/R.drawable.broken_clouds"
        android:targetActivity="io.github.erikjhordanrey.livebinding.view.DcCharacterActivity">

        <intent-filter>

            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />

        </intent-filter>

    </activity-alias>

    <activity-alias
        android:name=".MainActivityAlias"
        android:enabled="false"
        android:icon="@drawable/R.drawable.few_clouds"
        android:label="@string/app_name"
        android:roundIcon="@drawable/R.drawable.few_clouds"
        android:targetActivity="io.github.erikjhordanrey.livebinding.view.DcCharacterActivity">

        <intent-filter>

            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />

        </intent-filter>

    </activity-alias>

    <!--and so on....-->
</application>

</manifest>

在 MainActivity 文件中,您必须根据天气情况更改图标。

private void newicon() {
      
      // enable old icon
    PackageManager manager=getPackageManager();
    manager.setComponentEnabledSetting(new ComponentName(MainActivity.this,"com.prepare.makedirectory.MainActivity")
            ,PackageManager.COMPONENT_ENABLED_STATE_DISABLED,PackageManager.DONT_KILL_APP);
      
      // enable new icon
    manager.setComponentEnabledSetting(new ComponentName(MainActivity.this,"com.prepare.makedirectory.MainActivityAlias")
            ,PackageManager.COMPONENT_ENABLED_STATE_ENABLED,PackageManager.DONT_KILL_APP);
    Toast.makeText(MainActivity.this,"Enable New Icon" ,Toast.LENGTH_LONG).show();
}

您可以在 link 中找到整篇文章: https://www.geeksforgeeks.org/how-to-change-app-icon-of-android-programmatically-in-android/

请尝试此代码。

public class FirstFragment extends Fragment {

    private WeatherDataViewModel viewModel;

    public FirstFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View rootView = inflater.inflate(R.layout.fragment_first, container, false);
        // For displaying weather data
        // all field in Java should be type in camelCase, so not current_temp but currentTemp, not Cloud_out but cloudOut
        // Capitalize name is for class not field
        final TextView current_temp = rootView.findViewById(R.id.textView10);
        final TextView current_output = rootView.findViewById(R.id.textView11);
        final TextView rise_time = rootView.findViewById(R.id.textView25);
        final TextView set_time = rootView.findViewById(R.id.textView26);
        final TextView temp_out = rootView.findViewById(R.id.textView28);
        final TextView Press_out = rootView.findViewById(R.id.textView29);
        final TextView Humid_out = rootView.findViewById(R.id.textView30);
        final TextView Ws_out = rootView.findViewById(R.id.textView33);
        final TextView Visi_out = rootView.findViewById(R.id.textView34);
        final TextView Cloud_out = rootView.findViewById(R.id.textView35);
        final ImageView imageofWeather = rootView.findViewById(R.id.imageView2);


        // Get our ViewModel instance
        viewModel = new ViewModelProvider(this).get(WeatherDataViewModel.class);

        // And whenever the data changes, refresh the UI
        viewModel.getWeatherDataLiveData().observe(getViewLifecycleOwner(), data -> {

            Drawble drawableResource; // default added in switch

            if (data != null) {
                current_temp.setVisibility(View.VISIBLE);
                current_temp.setText(data.getMain().getTemp() + " ℃"); // for that you can use strings resource and templates more in https://developer.android.com/guide/topics/resources/string-resource.html#formatting-strings
                current_output.setVisibility(View.VISIBLE);
                current_output.setText(data.getWeather().get(0).getDescription());
                rise_time.setVisibility(View.VISIBLE);
                rise_time.setText(data.getSys().getSunrise() + " ");
                set_time.setVisibility(View.VISIBLE);
                set_time.setText(data.getSys().getSunset() + " ");
                temp_out.setVisibility(View.VISIBLE);
                temp_out.setText(data.getMain().getTemp() + " ℃");
                Press_out.setVisibility(View.VISIBLE);
                Press_out.setText(data.getMain().getPressure() + " hpa");
                Humid_out.setVisibility(View.VISIBLE);
                Humid_out.setText(data.getMain().getHumidity() + " %");
                Ws_out.setVisibility(View.VISIBLE);
                Ws_out.setText(data.getWind().getSpeed() + " Km/h");
                Visi_out.setVisibility(View.VISIBLE);
                Visi_out.setText(data.getVisibility() + " m");
                Cloud_out.setVisibility(View.VISIBLE);
                Cloud_out.setText(data.getClouds().getAll() + " %");

                Drawable drawableResource; // default icon is set in the switch
            switch (data.getWeather().get(0).getIcon())  {
                case WeaterIcon.SUN:
                    drawableResource = ContextCompat.getDrawable(requireActivity(), R.drawable.sun);
                    break;
                case WeatherIcon.Cloud1:
                        drawableResource = ContextCompat.getDrawable(requireActivity(), R.drawable.broken_clouds); //reference to drawable id
                        break;
                case WeatherIcon.Cloud2:
                        drawableResource = ContextCompat.getDrawable(requireActivity(), R.drawable.few_clouds); //reference to drawable id
                        break;
                case WeatherIcon.Cloud3:
                        drawableResource = ContextCompat.getDrawable(requireActivity(), R.drawable.scattered_clouds); //reference to drawable id
                        break;
                case WeatherIcon.Rain1:
                        drawableResource = ContextCompat.getDrawable(requireActivity(), R.drawable.small_rain); //reference to drawable id
                        break;
                case WeatherIcon.Rain2:
                        drawableResource = ContextCompat.getDrawable(requireActivity(), R.drawable.shower_rain); //reference to drawable id
                        break;
                case WeatherIcon.Thunder:
                        drawableResource = ContextCompat.getDrawable(requireActivity(), R.drawable.thunderstorm); //reference to drawable id
                        break;
                case WeatherIcon.Snow:
                        drawableResource = ContextCompat.getDrawable(requireActivity(), R.drawable.snow); //reference to drawable id
                        break;
                case WeatherIcon.Mist:
                        drawableResource = ContextCompat.getDrawable(requireActivity(), R.drawable.mist); //reference to drawable id
                        break;

                //add a default of any background if error occurs
                default:
                    drawableResource = ContextCompat.getDrawable(requireActivity(), R.drawable.any_background);
                    break;
           
                }
             imageOfWeather.setImageDrawable(drawableResource);

            } else {
                Log.e("TAG", "No City found");
                current_temp.setVisibility(View.GONE);
                current_output.setVisibility(View.GONE);
                rise_time.setVisibility(View.GONE);
                set_time.setVisibility(View.GONE);
                temp_out.setVisibility(View.GONE);
                Press_out.setVisibility(View.GONE);
                Humid_out.setVisibility(View.GONE);
                Ws_out.setVisibility(View.GONE);
                Visi_out.setVisibility(View.GONE);
                Cloud_out.setVisibility(View.GONE);
                Toast.makeText(requireActivity(), "No City found", Toast.LENGTH_SHORT).show();
            }
        });

        return rootView;
    }

    public void getWeatherData(String name) {
        // The ViewModel controls loading the data, so we just
        // tell it what the new name is - this kicks off loading
        // the data, which will automatically call through to
        // our observe() call when the data load completes
        viewModel.setCityName(name);
    }
}