2017-08-11 47 views
8

मैंने जवाब देने के लिए घंटों बिताए हैं और वास्तव में इसे हल करने का कोई विचार नहीं है। तो चलो व्यवसाय के लिए नीचे लाने के लिए करते हैं:छवि के चारों ओर फ्लो टेक्स्टव्यू

एक छवि और एक TextView नहीं है और मैं इस तरह ImageView आसपास TextView प्रवाह की जरूरत है:

enter image description here

पहले संभव समाधान https://github.com/deano2390/FlowTextView उपयोग करने के लिए हो सकता है woult लेकिन यह है TextView का विस्तार नहीं कर रहा है इसलिए यह पुस्तकालय मेरे कारणों के लिए उपयुक्त नहीं है।

दूसरा समाधान LeadingMarginSpan.LeadingMarginSpan2 अवधि का उपयोग किया जाएगा, लेकिन यह पाठ के अंदर प्रत्येक n लाइनों (इस जवाब में तरह ->How to layout text to flow around an image) के लिए प्रत्येक पैरा पर प्रभावित करता है, तो मैं इस तरह ख़ाली मिलती है:

enter image description here

लेकिन मैं केवल पहली एन लाइनों के लिए मार्जिन सेट करना चाहता था! तब मैंने LeadingMarginSpan.Standart को लागू करने और काउंटर बनाने और getLeadingMargin(first: Boolean): Int फ़ंक्शन आमंत्रण में इसे बढ़ाने का निर्णय लिया। जब काउंटर वांछनीय मूल्य तक पहुंच जाता है, तो फ़ंक्शन 0 मार्जिन चौड़ाई के रूप में देता है। और फिर एक असफल रहा है! TextView लाइनों को भरने के बजाय, पाठ बस बाईं ओर चला गया और दृश्य के अंत में फैल गया नहीं!

युपीडी: हाँ, मैं यहाँ में onGlobalLayoutListener का उपयोग किया है

enter image description here

ठीक है, एक और समाधान मैं इस सवाल का जवाब https://stackoverflow.com/a/27064368/7218592 ठीक पाया लिए googling, मैं सब कुछ के रूप में वर्णित और कोड लागू किया किया है:

  //set left margin of desirable width 
      val params: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) 
      params.leftMargin = holder.imageContainerHeight!! 
      params.addRule(RelativeLayout.BELOW, holder.mNumberAndTimeInfo!!.id) 
      holder.mCommentTextView!!.layoutParams = params 
      if (holder.commentTextViewOnGlobalLayoutListener != null) 
       holder.mCommentTextView!!.viewTreeObserver.removeOnGlobalLayoutListener(
         holder.commentTextViewOnGlobalLayoutListener) 

      //add onGlobalLayoutListener 
      holder.mCommentTextView!!.viewTreeObserver.addOnGlobalLayoutListener(
        if (holder.commentTextViewOnGlobalLayoutListener != null) 
         holder.commentTextViewOnGlobalLayoutListener 
        else CommentTextViewOnGlobalLayoutListener(holder, 
          SpannableString(HtmlCompat.fromHtml(
          mView.getActivity(), commentDocument.html(), 0, 
          null, SpanTagHandlerCompat(mView.getActivity())))))` 

मेरे OnGlobalLayoutListener इस तरह दिखता है: `

class CommentTextViewOnGlobalLayoutListener(
      val holder: CommentAndFilesListViewViewHolder, val commentSpannable: Spannable) : 
      ViewTreeObserver.OnGlobalLayoutListener { 
     val LOG_TAG: String = CommentTextViewOnGlobalLayoutListener::class.java.simpleName 

override fun onGlobalLayout() { 
     holder.mCommentTextView!!.viewTreeObserver.removeGlobalOnLayoutListener(this) 

     //when textview layout is drawn, get the line end to spanify only the needed text 
     val charCount = holder.mCommentTextView!!.layout.getLineEnd(Math.min(
       holder.mCommentTextView!!.layout.lineCount - 1, 
       CommentLeadingMarginSpan.computeLinesToBeSpanned(holder))) 
     if (charCount <= commentSpannable.length) { 
      commentSpannable.setSpan(CommentLeadingMarginSpan(holder), 
        0, charCount, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) 
     } 

     //set the left margin back to zero 
     (holder.mCommentTextView!!.layoutParams as RelativeLayout.LayoutParams).leftMargin = 0 
     holder.mCommentTextView!!.text = commentSpannable 
    } 
} 

`

अच्छा, यह काम करता है। लेकिन यह कितना भयानक काम करता है! चूंकि मैं व्यू धारक पैटर्न का उपयोग कर रहा हूं, मुझे श्रोता को एक चर रखना है और इसे हटाया नहीं गया है और इसे सफलतापूर्वक हटा दिया गया है क्योंकि onGlobalLayout फ़ंक्शन समय में नहीं बुलाया गया था! और इसे बहुत देर हो चुकी है, इसलिए आपको 300 एमएस इंतजार करना होगा और फिर TextView के सभी "पुनर्निर्माण" को देखना होगा और यह घृणित रूप से दिखता है!

तो, मेरे सवाल यह है: कैसे, TextView में पहले n लाइनों के लिए मार्जिन बनाने के लिए इससे पहले कि यह यूआई पर तैयार किया गया है?

+0

मैं यहाँ एक अलग दृष्टिकोण की कोशिश करेगा, मैं वेब दृश्य यहाँ का उपयोग करें और वहाँ में छवि और पाठ स्थापित करेगा –

+0

वेब-दृश्य देखते हैं, क्योंकि एक विकल्प नहीं है कई कस्टम क्लिक करने योग्य तक फैला है कि मैं जरूरत संभालने के लिए। मैं उन्हें त्याग नहीं सकता :( – koresuniku

+0

संभावित छवि का एक डुप्लिकेट [छवि के चारों ओर ले जाने के लिए लेआउट टेक्स्ट कैसे करें] (https://stackoverflow.com/questions/2248759/how-to-layout-text-to-flow-around- एक छवि) –

उत्तर

0

अंत में, मैंने सबसे अच्छा समाधान खोजने में कामयाब रहा है। यह वांछित चौड़ाई के TextView का एक नकली बनाने पर आधारित है, सबसे पहले StaticLayout

  1. का उपयोग कर, की (प्रदर्शन चौड़ाई से सिर्फ घटाना सभी पक्ष paddings और छवि कंटेनर चौड़ाई) हमारे TextView की चौड़ाई की गणना करते हैं पिक्सेल में
  2. दूसरा, हमें छवि कंटेनर की ऊंचाई (पिक्सल में) की आवश्यकता होगी।
  3. तीसरे, अभ्यास से पता चलता है के रूप में, StaticLayout पर ध्यान नहीं देता पंक्ति विराम ("\n" या "\r"), तो हम क्रम में एकल, लाइनों गैर तोड़ने में हमारी स्ट्रिंग विभाजित करने की आवश्यकता करने के लिए सफलतापूर्वक नकली TextView लेआउट: val commentParts = spannable.toString().split("\r")
  4. फिर, निम्न एल्गोरिदम प्रत्येक पंक्ति के लिए StaticLayout उदाहरण बनाता है, और जांच करता है कि रेखाएं छवि कंटेनर ऊंचाई से अधिक हैं या नहीं। यदि वे करते हैं, तो हम अंत में छवि कंटेनर के दाईं ओर स्थित अंतिम पंक्ति के अंतिम चार की स्थिति प्राप्त कर सकते हैं। और फिर हम, खुद से एक लाइन ब्रेक बनाने के क्रम में जाने के लिए LeadingMarginSpanLayout में पता [end + 1] चार स्थिति के साथ शुरू मार्जिन बनाने को रोकने के लिए की जरूरत है:

    var endReached: Boolean = false; 
          commentParts.forEach { 
           if (endReached) [email protected] 
    
           val layout: StaticLayout = StaticLayout(it, holder.mCommentTextView!!.paint, 
             textViewWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0f, false) 
           if (layout.lineCount > 0) { 
            var localHeight: Int 
    
            for (lineIndex in 0..layout.lineCount - 1) { 
             localHeight = layout.getLineBottom(lineIndex) 
             if (localHeight + totalHeightOfLines > imageContainerHeight) { 
              endReached = true 
              end = layout.getLineEnd(lineIndex) 
              val spannableStringBuilder = SpannableStringBuilder(spannable) 
              if (spannable.substring(end - 1, end) != "\n" && 
                spannable.substring(end - 1, end) != "\r") { 
               if (spannable.substring(end - 1, end) == " ") { 
                spannableStringBuilder.replace(end - 1, end, "\n") 
               } else { 
                spannableStringBuilder.insert(end, "\n") 
               } 
              } 
              spannable = SpannableString(spannableStringBuilder) 
              break 
             } 
            } 
            totalHeightOfLines += layout.lineCount * holder.mCommentTextView!!.lineHeight 
           } 
          } 
    
  5. और अंत में, spannable स्ट्रिंग पर LeadingMarginSpan2 सेट:

    spannable.setSpan(CommentLeadingMarginSpan2(
            CommentLeadingMarginSpan2.calculateLeadingMarginWidthInPx(holder)), 
            0, if (end == 0) spannable.length else end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) 
    holder.mCommentTextView!!.text = spannable 
    holder.mCommentTextView!!.requestLayout() 
    
  6. आखिरकार, अवधि सही ढंग से सेट की गई है!

    !

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