2010-11-13 6 views
5

जब आप एंड्रॉइड 2.2 में लाइववैलपेपर बनाते हैं तो आपको ड्रॉ करने के लिए कैनवास (या जो भी 3 डी समतुल्य है) मिलता है। मैं कैनवास कमांड का उपयोग करके स्क्रैच से सब कुछ बनाने या प्री-रेंडर यूआई बिटमैप लोड करने के बजाय अंतर्निहित एंड्रॉइड यूआई टूल्स का उपयोग करके कुछ तत्वों को आकर्षित करना चाहता हूं।एंड्रॉइड पर लाइववैलपेपर में लेआउट संसाधनों का उपयोग

एक दृश्य को बिटमैप में कनवर्ट करना ठीक काम करता है। यानी यह बहुत अच्छा काम करता है:

// For example this works: 
TextView view = new TextView(ctx); 
view.layout(0, 0, 200, 100); 
view.setText("test"); 
Bitmap b = Bitmap.createBitmap(200, 100, Bitmap.Config.ARGB_8888);     
Canvas tempC = new Canvas(b); 
view.draw(tempC); 
c.drawBitmap(b, 200, 100, mPaint); 

लेकिन, बच्चों के साथ लिनियरलाउट को परिवर्तित करने से समस्याएं आती हैं। आप केवल लाइनरलाइट स्वयं और उसके किसी भी बच्चे को प्राप्त नहीं करते हैं। उदाहरण के लिए, यदि मैंने लाइनरलाइट को एक सफेद पृष्ठभूमि रखने के लिए सेट किया है तो मुझे एक अच्छी तरह से प्रस्तुत सफेद बॉक्स मिलता है, लेकिन टेक्स्टव्यू बच्चों में से कोई भी बिटमैप में नहीं है। मैंने ड्रॉइंग कैश का उपयोग इसी तरह के परिणामों के साथ करने का भी प्रयास किया है।

मैं जिस कोड का उपयोग कर रहा हूं वह क्यूब उदाहरण है जिसमें केवल अतिरिक्त ड्रॉ कमांड होने के साथ ही परिवर्तन शामिल हैं। LinearLayout एक टोस्ट के रूप में ठीक काम करता है या नियमित दृश्य के रूप में (यानी सब कुछ अच्छी तरह से दिखाया जाता है), लाइववैलपेपर पर मुझे जो भी मिलता है वह रैखिकलायआउट की पृष्ठभूमि प्रदान करता है।

inflater = (LayoutInflater)getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
layout = (LinearLayout) inflater.inflate(com.example.android.livecubes.R.layout.testLinearLayout, null); 
layout.layout(0, 0, 400, 200); 

Bitmap b = Bitmap.createBitmap(400, 200, Bitmap.Config.ARGB_8888); 
Canvas tempC = new Canvas(b); 
layout.draw(tempC); 
c.drawBitmap(b, 10, 200, mPaint); 

क्या किसी को पता है कि बच्चों को मेरे बिटमैप में उचित रूप से प्रस्तुत करने के लिए कुछ विशेष करने की आवश्यकता है या नहीं? यानी क्या मुझे लेआउट को बाकी बच्चों को प्रस्तुत करने के लिए कुछ खास करने की ज़रूरत है? क्या मुझे सभी बच्चों को कुछ करने के लिए एक समारोह लिखना चाहिए?

मैं अपने आप को सब कुछ जोड़ सकता हूं, क्योंकि प्रदर्शन काफी स्थिर है (यानी मैं इसे एक बार खींचता हूं और पृष्ठभूमि पर आकर्षित करने के लिए बिटमैप की एक प्रति रखता हूं) यह मेरे लिए आसान लगता है और अभी भी बहुत ही कुशल है।

संपादित करें: लेआउट यह लगता है जैसे कि लेआउट नीचे दृश्य पेड़ प्रगति नहीं कर रहा है की राज्य में थोड़ा अधिक खुदाई करते समय (यानी LinearLayout हो जाता है अपने लेआउट अभिकलन जब मैं लेआउट (कहते हैं), लेकिन बच्चों एक शून्य (0x0) आकार है)। 2008 android developer post में रोमैन गाय की पोस्ट के मुताबिक। आपको लेआउट पास के लिए इंतजार करना होगा या लेआउट को मजबूर करना होगा। समस्या यह है कि मैं एक लाइन पेपर इंजन से लेआउट व्यू समूह से जुड़ा हुआ एक लाइन पेपर इंजन से लेआउट पास की प्रतीक्षा कैसे कर सकता हूं? और यदि लेआउट को आपको बाएं, ऊपर, दाएं, नीचे सेट करने की आवश्यकता होती है तो मैं प्रत्येक बच्चे तत्व को मैन्युअल रूप से कैसे ले सकता हूं, जब मुझे नहीं पता कि ये क्या होना चाहिए।

मैंने बल देने की कोशिश की है बच्चों पर ध्यान दें लेकिन यह या तो मदद नहीं करता है। मुझे यकीन नहीं है कि लेआउट फ्रेमवर्क दृश्यों के पीछे कैसे काम करता है (इसके अलावा यह दो पास लेआउट करता है)। क्या लेआउट पास मैन्युअल रूप से करने का कोई तरीका है, यानी अभी? चूंकि यह एक गतिविधि नहीं है, इसलिए मुझे नहीं लगता कि सामान्य पृष्ठभूमि सामग्री बहुत सी तरह से हो रही है।

+0

क्या आपने प्रस्तावित समाधान लागू किया है?मैं एक ही दृष्टिकोण का मूल्यांकन कर रहा हूं, लेकिन अपने अनुभवों से सीखना चाहूंगा – dparnas

उत्तर

8

लाइव वॉलपेपर को विशेष रूप से मानक यूआई विजेट का उपयोग करने के लिए डिज़ाइन नहीं किया गया था। हालांकि वैसे भी उनका उपयोग करना संभव है। आपको दृश्य पर पहले कॉलिंग उपाय() द्वारा लेआउट को पास करना होगा, फिर लेआउट()। आप मेरे presentation में अधिक जानकारी प्राप्त कर सकते हैं।

+13

@ जस्टिन बुसर मैं उन इंजीनियरों में से एक हूं जिन्होंने एंड्रॉइड टीम पर लाइव वॉलपेपर डिजाइन और कार्यान्वित किए हैं। जिन कक्षाओं का आप उल्लेख करते हैं उनके पास मानक यूआई विजेट्स के साथ कुछ लेना देना नहीं है जिनके बारे में हम बात कर रहे हैं। मुद्दा यह है कि आप लाइव वॉलपेपर पर सीधे दृश्य जोड़ नहीं सकते हैं (setContentView(), addView(), आदि का उपयोग कर) उदाहरण के लिए, एक सूची दृश्य। मैं जिस प्रस्तुति से जुड़ा हुआ हूं, वह मापने और लेआउट को स्वयं कैसे देखता है। –

+1

प्रस्तुति दृश्यों पर माप() और लेआउट() को कॉल करने के तरीके के बारे में बताती है। एक बार व्यू को मापने और रखे जाने के बाद, इसे कैनवास पर खींचा जा सकता है, उदाहरण के लिए लाइव वॉलपेपर पर। –

3

यहां एक दृश्य समूह, बटन और छविदृश्य का एक उदाहरण दिया गया है और लाइव वॉलपेपर में प्रदर्शित किया गया है। यदि आप विंडो प्रकार को 0 पर सेट करते हैं तो आप नल विंडो टोकन बग के आसपास भी काम कर सकते हैं और विंडोमैनेजर के माध्यम से सीधे दृश्य जोड़ सकते हैं। आपको अपवाद को पकड़ना होगा और परिणाम कुछ हद तक अनियमित हैं लेकिन यह अधिकांश भाग के लिए काम करता है।

import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.PixelFormat; 
import android.service.wallpaper.WallpaperService; 
import android.util.Log; 
import android.view.Gravity; 
import android.view.SurfaceHolder; 
import android.view.SurfaceHolder.Callback; 
import android.view.ViewGroup; 
import android.view.WindowManager; 
import android.view.WindowManager.LayoutParams; 
import android.widget.Button; 
import android.widget.ImageView; 
import android.widget.LinearLayout; 

public class UIWidgetWallpaper extends WallpaperService 
    { 

     private final String TAG   = getClass().getSimpleName(); 
     final static int  pixFormat = PixelFormat.RGBA_8888; 
     protected ImageView  imageView; 
     protected WindowManager windowManager; 
     protected LayoutParams layoutParams; 
     protected WidgetGroup widgetGroup; 
     protected SurfaceHolder surfaceHolder; 
     protected Button  button; 

     @Override 
     public Engine onCreateEngine() 
      { 
       Log.i(TAG, "onCreateEngine"); 
       return new UIWidgetWallpaperEngine(); 
      } 

     public class WidgetGroup extends ViewGroup 
      { 

       private final String TAG = getClass().getSimpleName(); 

       public WidgetGroup(Context context) 
        { 
         super(context); 
         Log.i(TAG, "WidgetGroup"); 
         setWillNotDraw(true); 
        } 

       @Override 
       protected void onLayout(boolean changed, int l, int t, int r, int b) 
        { 
         layout(l, t, r, b); 
        } 

      } 

     public class UIWidgetWallpaperEngine extends Engine implements Callback 
      { 

       private final String TAG = getClass().getSimpleName(); 

       @Override 
       public void onCreate(SurfaceHolder holder) 
        { 
         Log.i(TAG, "onCreate"); 
         super.onCreate(holder); 
         surfaceHolder = holder; 
         surfaceHolder.addCallback(this); 
         imageView = new ImageView(getApplicationContext()); 
         imageView.setClickable(false); 
         imageView.setImageResource(R.drawable.icon); 
         widgetGroup = new WidgetGroup(getApplicationContext()); 
         widgetGroup.setBackgroundDrawable(getWallpaper()); 
         widgetGroup.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); 
         widgetGroup.setAddStatesFromChildren(true); 
         holder.setFormat(pixFormat); 
         LinearLayout.LayoutParams imageParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 
         imageParams.weight = 1.0f; 
         imageParams.gravity = Gravity.CENTER; 
         widgetGroup.addView(imageView, imageParams); 
         button = new Button(getApplicationContext()); 
         button.setText("Test Button"); 
         LinearLayout.LayoutParams buttonParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 
         buttonParams.weight = 1.0f; 
         buttonParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; 
         widgetGroup.addView(button, buttonParams); 
        } 

       @Override 
       public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) 
        { 
         Log.i(TAG, "surfaceChanged: "); 
         synchronized(surfaceHolder) 
          { 
           Canvas canvas = surfaceHolder.lockCanvas(); 
           widgetGroup.layout(0, 0, width, height); 
           imageView.layout(0, 0, width/2, height); 
           button.layout(width/2, height - 100, width, height); 
           widgetGroup.draw(canvas); 
           surfaceHolder.unlockCanvasAndPost(canvas); 
          } 
        } 

       @Override 
       public void surfaceCreated(SurfaceHolder holder) 
        { 
        } 

       @Override 
       public void surfaceDestroyed(SurfaceHolder holder) 
        { 
        } 

      } 

    } 
+0

और यही कारण है कि हमारे पास अच्छी चीजें नहीं हो सकतीं ... "आपको अपवाद को पकड़ना होगा और परिणाम कुछ हद तक अनियमित हैं लेकिन यह अधिकांश भाग के लिए काम करता है।" वास्तव में??? – Dan

+3

मेरा उत्तर ज्यादातर उस प्रतिक्रिया का था जो कहता है "लाइव वॉलपेपर बहुत ही विशेष रूप से मानक यूआई विगेट्स का उपयोग न करने के लिए डिज़ाइन किए गए थे।" जो एक हास्यास्पद और भ्रामक जवाब है। ऐसा कहने की तरह है कि हवाई जहाज "विशेष रूप से पनडुब्बी नहीं होने के लिए डिजाइन किए गए थे"। मेरा मुद्दा मूल रूप से इसलिए है क्योंकि आप कुछ पानी के सबूत नहीं बनाते हैं इसका मतलब यह नहीं है कि यह नहीं किया जा सकता है। उस उदाहरण कोड को लिखने में 15 मिनट मैंने साबित किया कि वास्तव में यह किया जा सकता है, हालांकि मैं वास्तव में अपने बिंदु को साबित करने के बाद इसे पूरी तरह से डीबग करने का इच्छुक नहीं था, इसलिए त्रुटि को पकड़ने के बारे में चेतावनी। –

+0

यह समाधान वास्तव में काम करता है! : डी कोड थोड़ा गड़बड़ है और इसमें कुछ कोड की कमी है लेकिन यह काम करता है। हालांकि हमारे पास एक सवाल है। मेरे पास एक उप-वर्ग GLSurfaceView है, जिसमें एक 3 डी ऑब्जेक्ट प्रदान किया जा रहा है, मैं उन दोनों को कैसे दिखा सकता हूं जिसमें 3D ऑब्जेक्ट पृष्ठभूमि पर शीर्ष पर छवि दृश्य है? धन्यवाद! –

संबंधित मुद्दे