使用缩略图作为毕加索的占位符

时间:2014-12-04 17:03:25

标签: android picasso

从UX的角度来看,最好先向用户显示缩略图,直到真实图像完成加载,然后向他显示,但Picasso仅使用资源文件作为占位符:

Picasso.with(context)
    .load(url)
    .placeholder(R.drawable.user_placeholder)
    .into(imageView);

那么,我如何使用缩略图URL作为占位符?如果我应该两次使用毕加索,那该怎么办?

An issue已经在Picasso的github页面上打开了这个请求,但似乎根据JakeWharton它不会被添加到Picasso。那么我们怎么能用手头上的东西来做呢?

3 个答案:

答案 0 :(得分:30)

感谢raveN here&关于github上original request的评论,最后我得到了一个有效的解决方案:

Picasso.with(context)
       .load(thumb) // thumbnail url goes here
       .into(imageView, new Callback() {
            @Override
            public void onSuccess() {
                Picasso.with(context)
                        .load(url) // image url goes here
                        .placeholder(imageView.getDrawable())
                        .into(imageView);
            }
            @Override
            public void onError() {

            }
        });

这里的技巧是在第一次调用&之后从imageView(缩略图)中获取drawable。将其作为占位符传递给第二个调用

- 更新 -

我做了blog post描述整个场景

答案 1 :(得分:3)

你可以写一个简单的助手,两次调用毕加索(如你所说)。

我没有测试过它,但它应该像

一样
Picasso.with(context)
        .load(thumbnailUrl)
        .error(errorPlaceholderId)
        .into(imageView, new Callback() {
                        @Override
                        public void onSuccess() {
                                // TODO Call Picasso once again here
                        }

                        @Override
                        public void onError() {                             
                    }
            );

有几种不同的方法让你的毕加索被召唤两次。我能想到的一种方法(再次,未经测试)是

public static void loadImageWithCallback(String url, Callback callback) {
    Picasso.with(context)
        .load(url)
        .error(errorPlaceholderId)
        .into(imageView, callback);
}

public static void loadImage(String url) {
    Picasso.with(context)
        .load(url)
        .error(errorPlaceholderId)
        .into(imageView);
}

loadImageWithCallback("http://example.com/mythumbnail.jpg", new Callback() {

                    @Override
                    public void onSuccess() {
                        loadImage("http://example.com/myRealImage.jpg");    
                    }

                    @Override
                    public void onError() {                             
                }
}

编辑:我所知道的是Picasso提供了这种回调机制。我在我的应用程序中使用它来隐藏在加载图像之前显示的ProgressBar。我将隐藏它成功或错误回调 - 因此您可以选择在图像加载完成时收到通知。然后你可以再次调用它。我希望上述方法有效。

答案 2 :(得分:1)

我最初使用的是AbdelHady的解决方案,但发现只有在缩略图完成加载后才会加载较大的图像,所以我想出了这个。

假设您的项目中有实用程序类;

<html>
  <head>
    <title>Full player example</title>
    <!-- Uncomment the following meta tag if you have issues rendering this page on an intranet or local site. -->    
    <!-- <meta http-equiv="X-UA-Compatible" content="IE=edge"/> -->

    <script type="text/javascript">
        function init() {        // Master function, encapsulates all functions
            var video = document.getElementById("Video1");                                               
            if (video.canPlayType) {   // tests that we have HTML5 video support
                document.getElementById("buttonbar").style.display = "block";                
                video.src == "";
                function vidplay(evt) {
                    if (video.src == "") {  // inital source load
                        getVideo();
                    }
                    button = evt.target; //  get the button id to swap the text based on the state                                    
                    if (video.paused) {   // play the file, and display pause symbol
                        video.play();
                        button.textContent = "||";
                    } else {              // pause the file, and display play symbol  
                        video.pause();
                        button.textContent = ">";
                    }
                }
                //  load video file from input field
                function getVideo() {
                    var fileURL = "/lib/exe/fetch.php?media=experiment_log_books:sig0700.mp4";  // get input field                    
                    if (fileURL != "") {
                        video.src = fileURL;
                        video.load();  // if HTML source element is used
                        document.getElementById("play").click();  // start play
                    } else {
                        errMessage("Enter a valid video URL");  // fail silently
                    }
                }

                //  skip forward, backward, or restart
                function setTime(tValue) {
                    try {
                        if (tValue == 0) {
                            video.currentTime = tValue;
                        }
                        else {
                            video.currentTime += tValue;
                        }

                     } catch (err) {
                         // errMessage(err) // show exception
                     errMessage("Video content might not be loaded");
                       }
             }
                //  display an error message 
                function errMessage(msg) {
                // displays an error message for 5 seconds then clears it
                    document.getElementById("errorMsg").textContent = msg;
                    setTimeout("document.getElementById('errorMsg').textContent=''", 5000);
                }
                //  Play
                document.getElementById("play").addEventListener("click", vidplay, false);
                //  Restart
                document.getElementById("restart").addEventListener("click", function () {
                    setTime(0);
                }, false);
                //  Skip backward 10 seconds
                document.getElementById("rew").addEventListener("click", function () {
                    setTime(-10);
                }, false);
                //  Skip forward 10 seconds
                document.getElementById("fwd").addEventListener("click", function () {
                    setTime(10);
                }, false);
                //  set src == latest video file URL
                document.getElementById("loadVideo").addEventListener("click", getVideo, false);

                // fail with message 
                video.addEventListener("error", function (err) {
                    errMessage(err);
                }, true);

                // playback speed buttons
                document.getElementById("slower").addEventListener("click", function () {
                    video.playbackRate -= .25;
                }, false);
                document.getElementById("faster").addEventListener("click", function () {
                    video.playbackRate += .25;
                }, false);
                document.getElementById("normal").addEventListener("click", function () {
                    video.playbackRate = 1;
                }, false);

document.getElementById("play").click();
            } // end of runtime
        }// end of master         
    </script>

    </head>
    <body onload="init();" >        

    <video id="Video1" controls autoplay loop height="320" width="640" title="Sig 0700">            
         HTML5 Video is required for this example
    </video>

    <div id="buttonbar" style="display: none;")>
        <button id="restart" title="Restart button">[]</button> 
        <button id="slower" title="Slower playback button">-</button> 
        <button id="rew" title="Rewind button" >&lt;&lt;</button>
        <button id="play" title="Play button">&gt;</button>
        <button id="fwd" title="Forward button" >&gt;&gt;</button>
        <button id="faster" title="Faster playback button">+</button>
        <button id="normal" title="Reset playback rate button">=</button>        
    </div>    
    <div id= "inputField" style="display:none;" >
        <label>Type or paste a video URL: <br/>
        <input type="text" id="videoFile" style="width: 300px;"  title="video file input field" value="http://ie.microsoft.com/testdrive/ieblog/2011/nov/pp4_blog_demo.mp4" />        
        <button id="loadVideo" title="Load video button" >Load</button>
        </label>
    </div>
    <div title="Error message area" id="errorMsg" style="color:Red;"></div>  
    </body>
</html>

<强>用法:

public final class U {

public static void picassoCombo(final RequestCreator thumbnail,
                                final RequestCreator large,
                                final ImageView imageView) {
    Target target = new Target() {
        @Override
        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
            imageView.setImageBitmap(bitmap);
        }

        @Override
        public void onBitmapFailed(Drawable errorDrawable) {
            imageView.setImageDrawable(errorDrawable);
        }

        @Override
        public void onPrepareLoad(Drawable placeHolderDrawable) {
            thumbnail.into(imageView);
        }
    };

    imageView.setTag(target); // To prevent target from being garbage collected
    large.into(target);
}
}

在上面的示例中,首先设置占位符,然后设置缩略图URL,无论缩略图请求是完成,成功还是失败,都会在完成后设置大图像请求。如果大图像请求失败,则设置错误drawable。

唯一的问题是,如果您使用setIndicatorsEnabled(true)调试指标,则不会显示大型请求。据我所知,这似乎是根据this issue convo

设计的