我已经实现了一个扩展视图的新ImageLoaderView,如果我以编程方式设置xml,则代码可以正常工作。但由于这似乎很难,我试图让它在我的res布局文件夹中的xml工作,但我收到一个错误。以下是我的代码。
LoaderImageView:
package com.anon.android.test;
import java.io.IOException;
import java.net.MalformedURLException;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.os.Handler.Callback;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
/**
* Free for anyone to use, just say thanks and share :-)
* @author Blundell
*
*/
public class LoaderImageView extends LinearLayout{
private static final int COMPLETE = 0;
private static final int FAILED = 1;
private Context mContext;
private Drawable mDrawable;
private ProgressBar mSpinner;
private ImageView mImage;
/**
* This is used when creating the view in XML
* To have an image load in XML use the tag 'image="http://developer.android.com/images/dialog_buttons.png"'
* Replacing the url with your desired image
* Once you have instantiated the XML view you can call
* setImageDrawable(url) to change the image
* @param context
* @param attrSet
*/
public LoaderImageView(final Context context, final AttributeSet attrSet) {
super(context, attrSet);
final String url = attrSet.getAttributeValue(null, "image");
if(url != null){
instantiate(context, url);
} else {
instantiate(context, null);
}
}
/**
* This is used when creating the view programatically
* Once you have instantiated the view you can call
* setImageDrawable(url) to change the image
* @param context the Activity context
* @param imageUrl the Image URL you wish to load
*/
public LoaderImageView(final Context context, final String imageUrl) {
super(context);
instantiate(context, imageUrl);
}
/**
* First time loading of the LoaderImageView
* Sets up the LayoutParams of the view, you can change these to
* get the required effects you want
*/
private void instantiate(final Context context, final String imageUrl) {
mContext = context;
mImage = new ImageView(mContext);
mImage.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
mSpinner = new ProgressBar(mContext);
mSpinner.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
mSpinner.setIndeterminate(true);
addView(mSpinner);
addView(mImage);
if(imageUrl != null){
setImageDrawable(imageUrl);
}
}
/**
* Set's the view's drawable, this uses the internet to retrieve the image
* don't forget to add the correct permissions to your manifest
* @param imageUrl the url of the image you wish to load
*/
public void setImageDrawable(final String imageUrl) {
mDrawable = null;
mSpinner.setVisibility(View.VISIBLE);
mImage.setVisibility(View.GONE);
new Thread(){
public void run() {
try {
mDrawable = getDrawableFromUrl(imageUrl);
imageLoadedHandler.sendEmptyMessage(COMPLETE);
} catch (MalformedURLException e) {
imageLoadedHandler.sendEmptyMessage(FAILED);
} catch (IOException e) {
imageLoadedHandler.sendEmptyMessage(FAILED);
}
};
}.start();
}
/**
* Callback that is received once the image has been downloaded
*/
private final Handler imageLoadedHandler = new Handler(new Callback() {
public boolean handleMessage(Message msg) {
switch (msg.what) {
case COMPLETE:
mImage.setImageDrawable(mDrawable);
mImage.setVisibility(View.VISIBLE);
mSpinner.setVisibility(View.GONE);
break;
case FAILED:
default:
// Could change image here to a 'failed' image
// otherwise will just keep on spinning
break;
}
return true;
}
});
/**
* Pass in an image url to get a drawable object
* @return a drawable object
* @throws IOException
* @throws MalformedURLException
*/
private static Drawable getDrawableFromUrl(final String url) throws IOException, MalformedURLException {
return Drawable.createFromStream(((java.io.InputStream)new java.net.URL(url).getContent()), "name");
}
}
这是我的xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff">
<Button
android:id="@+id/button_weather9"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Back" />
<com.anon.android.test.LoaderImageview
android:id="@+id/weather_icon"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_horizontal"
android:scaleType="fitXY"
image="http://developer.android.com/images/dialog_buttons.png"
/>
</LinearLayout>
这就是我所说的:(在我的ImageLoading活动中 )
LoaderImageView image = (LoaderImageView) findViewById(R.id.weather_icon);
但是我收到了这个错误:
01-13 09:16:45.516: E/AndroidRuntime(216): Uncaught handler: thread main exiting due to uncaught exception
01-13 09:16:45.526: E/AndroidRuntime(216): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.anon.android.test/com.anon.android.test.ImageLoading}: android.view.InflateException: Binary XML file line #15: Error inflating class com.anon.android.test.LoaderImageview
01-13 09:16:45.526: E/AndroidRuntime(216): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2496)
01-13 09:16:45.526: E/AndroidRuntime(216): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
01-13 09:16:45.526: E/AndroidRuntime(216): at android.app.ActivityThread.access$2200(ActivityThread.java:119)
01-13 09:16:45.526: E/AndroidRuntime(216): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
01-13 09:16:45.526: E/AndroidRuntime(216): at android.os.Handler.dispatchMessage(Handler.java:99)
01-13 09:16:45.526: E/AndroidRuntime(216): at android.os.Looper.loop(Looper.java:123)
01-13 09:16:45.526: E/AndroidRuntime(216): at android.app.ActivityThread.main(ActivityThread.java:4363)
01-13 09:16:45.526: E/AndroidRuntime(216): at java.lang.reflect.Method.invokeNative(Native Method)
01-13 09:16:45.526: E/AndroidRuntime(216): at java.lang.reflect.Method.invoke(Method.java:521)
01-13 09:16:45.526: E/AndroidRuntime(216): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
01-13 09:16:45.526: E/AndroidRuntime(216): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
01-13 09:16:45.526: E/AndroidRuntime(216): at dalvik.system.NativeStart.main(Native Method)
01-13 09:16:45.526: E/AndroidRuntime(216): Caused by: android.view.InflateException: Binary XML file line #15: Error inflating class com.anon.android.test.LoaderImageview
01-13 09:16:45.526: E/AndroidRuntime(216): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:576)
01-13 09:16:45.526: E/AndroidRuntime(216): at android.view.LayoutInflater.rInflate(LayoutInflater.java:618)
01-13 09:16:45.526: E/AndroidRuntime(216): at android.view.LayoutInflater.inflate(LayoutInflater.java:407)
01-13 09:16:45.526: E/AndroidRuntime(216): at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
01-13 09:16:45.526: E/AndroidRuntime(216): at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
01-13 09:16:45.526: E/AndroidRuntime(216): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:198)
01-13 09:16:45.526: E/AndroidRuntime(216): at android.app.Activity.setContentView(Activity.java:1622)
01-13 09:16:45.526: E/AndroidRuntime(216): at com.anon.android.test.ImageLoading.onCreate(ImageLoading.java:22)
01-13 09:16:45.526: E/AndroidRuntime(216): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
01-13 09:16:45.526: E/AndroidRuntime(216): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
01-13 09:16:45.526: E/AndroidRuntime(216): ... 11 more
01-13 09:16:45.526: E/AndroidRuntime(216): Caused by: java.lang.ClassNotFoundException: com.anon.android.test.LoaderImageview in loader dalvik.system.PathClassLoader@44e8cad8
01-13 09:16:45.526: E/AndroidRuntime(216): at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:243)
01-13 09:16:45.526: E/AndroidRuntime(216): at java.lang.ClassLoader.loadClass(ClassLoader.java:573)
01-13 09:16:45.526: E/AndroidRuntime(216): at java.lang.ClassLoader.loadClass(ClassLoader.java:532)
01-13 09:16:45.526: E/AndroidRuntime(216): at android.view.LayoutInflater.createView(LayoutInflater.java:466)
01-13 09:16:45.526: E/AndroidRuntime(216): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:565)
01-13 09:16:45.526: E/AndroidRuntime(216): ... 20 more
我认为让我错误的是我在xml中声明我的LoaderImageView的方式。你能救我吗?
答案 0 :(得分:7)
您需要在布局的根元素中添加应用的package
,如下所示:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.anon.android.test"
.../>
然后当您为自定义视图充气时,会传递自定义属性,如下所示:
<com.anon.android.test.LoaderImageview
...
app:image="http://developer....png"/>
此外,我想您已在styleable attributes
内声明了resources
。
修改
要为styleable attribute
创建View
,请在项目的attrs.xml
文件夹中创建一个res\values
文件,内容应如下所示:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="LoaderImageView">
<attr name="image" format="string"/>
//other attributes..
</declare-styleable>
</resources>
答案 1 :(得分:1)
所以,与这个问题相关但不是同一个案例:我遇到了同样的问题,adb logcat输出并没有帮助那么多。
在查看我的代码后,我意识到我正在编写布局&#39; 查看&#39;注意&#39; 查看&#39;。显然,如果Android si试图膨胀的元素不存在或者名称无效,那么它会在没有非常有用的错误输出的情况下崩溃。