एंड्रॉइड टेक्स्टव्यू आउटलाइन टेक्स्ट


83

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


7
इस प्रश्न को पढ़ने और पेंट-स्ट्रोक समाधान का उपयोग करने पर विचार करने वाले किसी के लिए, कृपया ध्यान दें कि एंड्रॉइड 4.4 में स्ट्रोक के साथ एक बग है । यदि पाठ का आकार यदि 256 पिक्सेल से ऊपर है, तो यह बहुत ही अजीब स्ट्रोक प्रदान करता है। इस उत्तर में प्रस्तुत वैकल्पिक विधि के साथ रूपरेखा / आरेख तैयार करना है । मैं इसे हर स्ट्रोक-टाइप उत्तर पर स्पैम नहीं करना चाहता था, इसलिए इसे लोगों को जागरूक करने के लिए यहां डाल रहा हूं और उन्हें उस दुःख से बचाने के लिए जो मैं गया था।
टोनी चैन

जवाबों:


56

आप पाठ के पीछे एक छाया डाल सकते हैं, जो अक्सर पठनीयता में मदद कर सकता है। अपने हरे रंग के पाठ पर 50% पारभासी काली छाया के साथ प्रयोग करने का प्रयास करें। यह कैसे करें इस पर विवरण यहां दिया गया है: Android - पाठ पर छाया?

वास्तव में पाठ के चारों ओर एक स्ट्रोक जोड़ने के लिए, आपको कुछ और अधिक शामिल करने की आवश्यकता है, जैसे: आप एंड्रॉइड में मैपव्यू पर बॉर्डर के साथ टेक्स्ट कैसे आकर्षित करते हैं?


3
कृपया ध्यान दें कि एंड्रॉइड 4.4 में स्ट्रोक के साथ एक बग है । यदि पाठ का आकार यदि 256 पिक्सेल से ऊपर है, तो यह बहुत ही अजीब स्ट्रोक प्रदान करता है। इस उत्तर में प्रस्तुत वैकल्पिक पद्धति के साथ रूपरेखा / आघात तैयार करना है ।
टोनी चैन

क्या यह टिप्पणी पाठ्यपुस्तक या फ़ॉन्ट आकार को संदर्भित करती है?
जॉन

छाया काफी अच्छी नहीं है, सफेद पृष्ठभूमि लेआउट पर सफेद पाठ अभी भी उस काली छाया के साथ बहुत बुरा लग रहा है
user924

81

पाठ दृश्य में छाया का उपयोग करके रूपरेखा प्रभाव प्राप्त किया जा सकता है:

    android:shadowColor="#000000"
    android:shadowDx="1.5"
    android:shadowDy="1.3"
    android:shadowRadius="1.6"
    android:text="CCC"
    android:textAllCaps="true"
    android:textColor="@android:color/white"

यह सबसे अच्छा समाधान होना चाहिए। वह बहुत अच्छा था! धन्यवाद
Renan Bandeira

5
यह एक रूपरेखा के रूप में परिणाम नहीं करता है क्योंकि यह केवल दो पक्षों पर दिखाता है।
प्रतिबंध-जियोइंजीनियरिंग

मेरे लिए उत्तम हैं!!
Ely Dantas

यह छाया आउटलाइन के लिए बहुत कमजोर है
user924

55

इसलिए, थोड़ी देर से, लेकिन मैजिकटेक्स्ट्यूव अन्य चीजों के अलावा, पाठ की रूपरेखा बनाएगा

यहां छवि विवरण दर्ज करें

<com.qwerjk.better_text.MagicTextView
    xmlns:qwerjk="http://schemas.android.com/apk/res/com.qwerjk.better_text"
    android:textSize="78dp"
    android:textColor="#ff333333"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    qwerjk:strokeColor="#FFff0000"
    qwerjk:strokeJoinStyle="miter"
    qwerjk:strokeWidth="5"
    android:text="Magic" />

नोट: मैंने इसे बनाया है, और ओपी की तुलना में भविष्य के यात्रियों के लिए अधिक पोस्ट कर रहा हूं। यह बॉर्डरलाइन स्पैम है, लेकिन ऑन-टॉपिक होने के नाते, शायद स्वीकार्य है?


1
नमस्कार, हम EditText में दर्ज किए जा रहे पाठ पर इन जैसी सीमाओं को कैसे जोड़ सकते हैं?
तिललहुसैन २४'४४ को १४:४०

EditText के बारे में कोई विचार?
पयोट्र

dreamText.setStroke (4, Color.BLACK); dreamText.setTextColor (Color.WHITE); मैं इन सेटिंग्स का उपयोग कर रहा हूं, लेकिन मेरा टेक्स्ट रंग पारदर्शी है, मैं ब्लैक आउटलाइन देख सकता हूं। गलत क्या है?
मुहम्मद उमर

यह ठीक है, लेकिन यह वास्तव में एक सीमा नहीं जोड़ता है। यह बजाय पाठ लेता है और सीमा के रूप में outher किनारे का उपयोग करता है जो समान दृश्य परिणाम नहीं देता है।
वार्पजीत

1
इस समाधान onDrawको पुन: कॉल के कारण कॉल किया जाता है क्योंकि setTextColorअंदर कॉल होता है onDraw
18

23

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

  1. TextView वर्ग बढ़ाएँ
  2. ओवरराइड विधि को ओवरराइड करें
  3. भरने के लिए पेंट शैली सेट करें
  4. ड्रा मोड में टेक्स्ट रेंडर करने के लिए ड्रा पर पैरेंट क्लास को कॉल करें।
  5. वर्तमान पाठ रंग सहेजें।
  6. वर्तमान पाठ रंग को अपने स्ट्रोक रंग में सेट करें
  7. स्ट्रोके को पेंट स्टाइल सेट करें
  8. स्ट्रोक की चौड़ाई निर्धारित करें
  9. और पहले से रचे गए पाठ पर आघात करने के लिए माता-पिता को फिर से कॉल करें।

    package com.example.widgets;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.Typeface;
    import android.util.AttributeSet;
    import android.widget.Button;
    
    public class StrokedTextView extends Button {
    
        private static final int DEFAULT_STROKE_WIDTH = 0;
    
        // fields
        private int _strokeColor;
        private float _strokeWidth;
    
        // constructors
        public StrokedTextView(Context context) {
            this(context, null, 0);
        }
    
        public StrokedTextView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public StrokedTextView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
    
            if(attrs != null) {
                TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.StrokedTextAttrs);
                _strokeColor = a.getColor(R.styleable.StrokedTextAttrs_textStrokeColor,
                        getCurrentTextColor());         
                _strokeWidth = a.getFloat(R.styleable.StrokedTextAttrs_textStrokeWidth,
                        DEFAULT_STROKE_WIDTH);
    
                a.recycle();
            }
            else {          
                _strokeColor = getCurrentTextColor();
                _strokeWidth = DEFAULT_STROKE_WIDTH;
            } 
            //convert values specified in dp in XML layout to
            //px, otherwise stroke width would appear different
            //on different screens
            _strokeWidth = dpToPx(context, _strokeWidth);           
        }    
    
        // getters + setters
        public void setStrokeColor(int color) {
            _strokeColor = color;        
        }
    
        public void setStrokeWidth(int width) {
            _strokeWidth = width;
        }
    
        // overridden methods
        @Override
        protected void onDraw(Canvas canvas) {
            if(_strokeWidth > 0) {
                //set paint to fill mode
                Paint p = getPaint();
                p.setStyle(Paint.Style.FILL);        
                //draw the fill part of text
                super.onDraw(canvas);       
                //save the text color   
                int currentTextColor = getCurrentTextColor();    
                //set paint to stroke mode and specify 
                //stroke color and width        
                p.setStyle(Paint.Style.STROKE);
                p.setStrokeWidth(_strokeWidth);
                setTextColor(_strokeColor);
                //draw text stroke
                super.onDraw(canvas);      
               //revert the color back to the one 
               //initially specified
               setTextColor(currentTextColor);
           } else {
               super.onDraw(canvas);
           }
       }
    
       /**
        * Convenience method to convert density independent pixel(dp) value
        * into device display specific pixel value.
        * @param context Context to access device specific display metrics 
        * @param dp density independent pixel value
        * @return device specific pixel value.
        */
       public static int dpToPx(Context context, float dp)
       {
           final float scale= context.getResources().getDisplayMetrics().density;
           return (int) (dp * scale + 0.5f);
       }            
    }
    

बस इतना ही। यह वर्ग कस्टम XML विशेषताओं का उपयोग करता है जो XML लेआउट फ़ाइलों से स्ट्रोक रंग और चौड़ाई निर्दिष्ट करने में सक्षम करता है। इसलिए, आपको इन विशेषताओं को सबफ़ोल्डर के मानों में अपने attr.xml फ़ाइल में फ़ोल्डर 'रेस' के तहत जोड़ना होगा। अपनी attr.xml फ़ाइल में निम्नलिखित को कॉपी और पेस्ट करें।

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="StrokedTextAttrs">
        <attr name="textStrokeColor" format="color"/>    
        <attr name="textStrokeWidth" format="float"/>
    </declare-styleable>                

</resources>

एक बार जब आप इसके साथ हो जाते हैं, तो आप अपनी XML लेआउट फ़ाइलों में कस्टम StrokedTextView वर्ग का उपयोग कर सकते हैं और साथ ही स्ट्रोक रंग और चौड़ाई निर्दिष्ट कर सकते हैं। यहाँ एक उदाहरण है

<com.example.widgets.StrokedTextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Stroked text sample"
    android:textColor="@android:color/white"
    android:textSize="25sp"
    strokeAttrs:textStrokeColor="@android:color/black"
    strokeAttrs:textStrokeWidth="1.7" />

अपने प्रोजेक्ट के पैकेज के नाम के साथ पैकेज का नाम बदलना याद रखें। कस्टम XML विशेषताओं का उपयोग करने के लिए लेआउट फ़ाइल में xmlns नाम स्थान भी जोड़ें। आप अपने लेआउट फ़ाइल के रूट नोड में निम्न पंक्ति जोड़ सकते हैं।

xmlns:strokeAttrs="http://schemas.android.com/apk/res-auto"

2
क्या शानदार, सुरुचिपूर्ण समाधान है! मैंने इसे लागू किया और यह अच्छी तरह से काम करता है। मैंने बस textStrokeWidth को एक आयाम (और a.getDimensionPixelSize) में बदल दिया है। धन्यवाद!
dgmltn

1
अच्छा काम करता है, धन्यवाद। जैसा कि उन्होंने रूपरेखा पूरे पाठ को संभाला, मैंने अपने मामले में क्रम बदल दिया: पहले रूपरेखा को चित्रित किया गया और फिर पाठ को।
मदिनेर

2
बहुत अच्छा काम करता है। रूपरेखा का परीक्षण करने के लिए एंड्रॉइड स्टूडियो डिज़ाइन दृश्य का उपयोग न करें, प्रतिनिधित्व पर्याप्त रूप से सटीक नहीं है। बस गैर-मुद्दे पर 2h डिबगिंग बिताया।
llmora

7
इस समाधान के कारण अनंत संख्याएँ चालू हो जाएँगी, क्योंकि setTextColor अमान्य हैं।
गुलिआश

2
दरअसल, @ गुलश सही है। परीक्षण करने के बाद, एक बार इस पद्धति को कहा जाता है, यह invalidate()भीतर के कामकाज में दफन कॉल के कारण खुद को कॉल करने का एक अनंत लूप का कारण बनता है setTextColor। जब तक आप कोड की हर अंतिम पंक्ति को TextViewअपनी कक्षा में कॉपी नहीं करना चाहते, तब तक इसके चारों ओर एक ही रास्ता जो मैं देख सकता हूं वह है रिफ्लेक्शन का उपयोग करने के निजी mCurTextColor क्षेत्र तक पहुंच को बल देना TextViewयह उत्तर देखें कि मोटे तौर पर यह कैसे करना है। उपयोग field.set(this, colorInt)करने के बजाय बस उपयोग करें field.get()
वरुमच

23

रूपरेखा पाठ-छाया का समर्थन करती है लेकिन पाठ-रूपरेखा का समर्थन नहीं करती है। लेकिन एक चाल है: छाया ऐसी चीज है जो पारभासी है और लुप्त होती है। छाया को दो बार फिर से हिलाएं और सभी अल्फ़ा सम्‍मिलित हो जाएं और परिणाम एक रूपरेखा है।

एक बहुत ही सरल कार्यान्वयन विधि का विस्तार करता है TextViewऔर ओवरराइड करता draw(..)है। हर बार एक ड्रॉ का अनुरोध किया जाता है कि हमारा उपवर्ग 5-10 चित्र बनाता है।

public class OutlineTextView extends TextView {

    // Constructors

    @Override
    public void draw(Canvas canvas) {
        for (int i = 0; i < 5; i++) {
            super.draw(canvas);
        }
    }

}


<OutlineTextView
    android:shadowColor="#000"
    android:shadowRadius="3.0" />

3
आपका बहुत बहुत धन्यवाद। हालाँकि मैं इस पद्धति का उपयोग करता हूं: '@Override संरक्षित शून्य onDraw (कैनवास कैनवास) {के लिए (int i = 0; i <5; i ++) {super.onDraw (कैनवास); }} '
IHeartAndroid 11

1
अतिरिक्त जानकारी: एक को कॉन्टेक्ट और एट्रीब्यूटसेट के साथ कम से कम ctor को लागू करना होगा। अन्यथा आप में भागते हैं। java.lang.NoSuchMethodException: <init> [class android.content.Context, interface android.util.AttributeSet
बेवर

15

मैं बस यह पता लगाने की कोशिश कर रहा हूं कि यह कैसे करना है और ऑनलाइन एक अच्छा मार्गदर्शक नहीं मिल सकता है लेकिन अंततः यह पता लगा लिया है। जैसा कि स्टीव पोमेरॉय ने सुझाव दिया था, आपको कुछ और काम करने होंगे। उल्लिखित पाठ प्रभाव प्राप्त करने के लिए, आप पाठ को दो बार आकर्षित करते हैं: एक बार एक मोटी रूपरेखा के साथ और फिर दूसरी बार हम मुख्य पाठ को रूपरेखा के ऊपर खींचते हैं। लेकिन, यह काम आसान हो जाता है क्योंकि आप एसडीके के साथ दिए गए कोड नमूनों में से एक को आसानी से अपने एसडीके निर्देशिका में इस नाम के तहत अनुकूलित कर सकते हैं: "/ नमूने / Android- / ApiDemos / src / com / उदाहरण / Android /apis/view/LabelView.java "। जो कि यहां Android डेवलपर वेबसाइट पर भी मिल सकता है

आप जो कर रहे हैं, उसके आधार पर, यह देखना बहुत आसान है कि आपको केवल उस कोड में मामूली संशोधन करने की आवश्यकता होगी, जैसे कि इसे TextView से विस्तारित करने के लिए बदलना, आदि। इससे पहले कि मैं इस नमूने की खोज करता हूं मैं onMeasure () को ओवरराइड करना भूल गया ( आपको ऑनड्राइड () को ओवरराइड करने के अलावा करना चाहिए (जैसा कि एंड्रॉइड डेवलपर वेबसाइट पर "बिल्डिंग कस्टम कंपोनेंट्स गाइड" में उल्लेख किया गया है), जो इस बात का हिस्सा है कि मुझे क्यों परेशानी हो रही थी।

एक बार जब आप ऐसा कर लेते हैं, तो आप वही कर सकते हैं जो मैंने किया था:

public class TextViewOutline extends TextView {

private Paint mTextPaint;
private Paint mTextPaintOutline; //add another paint attribute for your outline
...
//modify initTextViewOutline to setup the outline style
   private void initTextViewOutline() {
       mTextPaint = new Paint();
       mTextPaint.setAntiAlias(true);
       mTextPaint.setTextSize(16);
       mTextPaint.setColor(0xFF000000);
       mTextPaint.setStyle(Paint.Style.FILL);

       mTextPaintOutline = new Paint();
       mTextPaintOutline.setAntiAlias(true);
       mTextPaintOutline.setTextSize(16);
       mTextPaintOutline.setColor(0xFF000000);
       mTextPaintOutline.setStyle(Paint.Style.STROKE);
       mTextPaintOutline.setStrokeWidth(4);

       setPadding(3, 3, 3, 3);
}
...
//make sure to update other methods you've overridden to handle your new paint object
...
//and finally draw the text, mAscent refers to a member attribute which had
//a value assigned to it in the measureHeight and Width methods
   @Override
   protected void onDraw(Canvas canvas) {
       super.onDraw(canvas);
       canvas.drawText(mText, getPaddingLeft(), getPaddingTop() - mAscent, 
           mTextPaintOutline);
       canvas.drawText(mText, getPaddingLeft(), getPaddingTop() - mAscent, mTextPaint);
   }

इसलिए, उल्लिखित पाठ प्रभाव प्राप्त करने के लिए, आप पाठ को दो बार खींचते हैं: एक बार एक मोटी रूपरेखा के साथ और फिर दूसरी बार हम मुख्य पाठ को रूपरेखा के ऊपर खींचते हैं।


9

@YGHM पर क्रेडिट छाया समर्थन जोड़ते हैं यहां छवि विवरण दर्ज करें

package com.megvii.demo;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;

public class TextViewOutline extends android.support.v7.widget.AppCompatTextView {

// constants
private static final int DEFAULT_OUTLINE_SIZE = 0;
private static final int DEFAULT_OUTLINE_COLOR = Color.TRANSPARENT;

// data
private int mOutlineSize;
private int mOutlineColor;
private int mTextColor;
private float mShadowRadius;
private float mShadowDx;
private float mShadowDy;
private int mShadowColor;

public TextViewOutline(Context context) {
    this(context, null);
}

public TextViewOutline(Context context, AttributeSet attrs) {
    super(context, attrs);
    setAttributes(attrs);
}

private void setAttributes(AttributeSet attrs) {
    // set defaults
    mOutlineSize = DEFAULT_OUTLINE_SIZE;
    mOutlineColor = DEFAULT_OUTLINE_COLOR;
    // text color   
    mTextColor = getCurrentTextColor();
    if (attrs != null) {
        TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.TextViewOutline);
        // outline size
        if (a.hasValue(R.styleable.TextViewOutline_outlineSize)) {
            mOutlineSize = (int) a.getDimension(R.styleable.TextViewOutline_outlineSize, DEFAULT_OUTLINE_SIZE);
        }
        // outline color
        if (a.hasValue(R.styleable.TextViewOutline_outlineColor)) {
            mOutlineColor = a.getColor(R.styleable.TextViewOutline_outlineColor, DEFAULT_OUTLINE_COLOR);
        }
        // shadow (the reason we take shadow from attributes is because we use API level 15 and only from 16 we have the get methods for the shadow attributes)
        if (a.hasValue(R.styleable.TextViewOutline_android_shadowRadius)
                || a.hasValue(R.styleable.TextViewOutline_android_shadowDx)
                || a.hasValue(R.styleable.TextViewOutline_android_shadowDy)
                || a.hasValue(R.styleable.TextViewOutline_android_shadowColor)) {
            mShadowRadius = a.getFloat(R.styleable.TextViewOutline_android_shadowRadius, 0);
            mShadowDx = a.getFloat(R.styleable.TextViewOutline_android_shadowDx, 0);
            mShadowDy = a.getFloat(R.styleable.TextViewOutline_android_shadowDy, 0);
            mShadowColor = a.getColor(R.styleable.TextViewOutline_android_shadowColor, Color.TRANSPARENT);
        }

        a.recycle();
    }

}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    setPaintToOutline();
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

private void setPaintToOutline() {
    Paint paint = getPaint();
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(mOutlineSize);
    super.setTextColor(mOutlineColor);
    super.setShadowLayer(0, 0, 0, Color.TRANSPARENT);

}

private void setPaintToRegular() {
    Paint paint = getPaint();
    paint.setStyle(Paint.Style.FILL);
    paint.setStrokeWidth(0);
    super.setTextColor(mTextColor);
    super.setShadowLayer(mShadowRadius, mShadowDx, mShadowDy, mShadowColor);
}


@Override
public void setTextColor(int color) {
    super.setTextColor(color);
    mTextColor = color;
}


public void setOutlineSize(int size) {
    mOutlineSize = size;
}

public void setOutlineColor(int color) {
    mOutlineColor = color;
}

@Override
protected void onDraw(Canvas canvas) {
    setPaintToOutline();
    super.onDraw(canvas);

    setPaintToRegular();
    super.onDraw(canvas);
}

}

अटर डिफाइन

<declare-styleable name="TextViewOutline">
    <attr name="outlineSize" format="dimension"/>
    <attr name="outlineColor" format="color|reference"/>
    <attr name="android:shadowRadius"/>
    <attr name="android:shadowDx"/>
    <attr name="android:shadowDy"/>
    <attr name="android:shadowColor"/>
</declare-styleable>

नीचे xml कोड

<com.megvii.demo.TextViewOutline
    android:id="@+id/product_name"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:layout_marginTop="110dp"
    android:background="#f4b222"
    android:fontFamily="@font/kidsmagazine"
    android:padding="10dp"
    android:shadowColor="#d7713200"
    android:shadowDx="0"
    android:shadowDy="8"
    android:shadowRadius="1"
    android:text="LIPSTICK SET"
    android:textColor="@android:color/white"
    android:textSize="30sp"
    app:outlineColor="#cb7800"
    app:outlineSize="3dp" />

8

यहाँ पर मैंने पाया है कि मैजिकटेक्स्ट्यूव के स्ट्रोक IMO से बेहतर काम करता है

@Override
protected void onDraw(Canvas pCanvas) {
    int textColor = getTextColors().getDefaultColor();
    setTextColor(mOutlineColor); // your stroke's color
    getPaint().setStrokeWidth(10);
    getPaint().setStyle(Paint.Style.STROKE);
    super.onDraw(pCanvas);
    setTextColor(textColor);
    getPaint().setStrokeWidth(0);
    getPaint().setStyle(Paint.Style.FILL);
    super.onDraw(pCanvas);
}

मुझे लगता है कि TextView के दाहिने हिस्से को क्रॉप किया जा रहा है - और रूपरेखा पूरी तरह से उस तरफ नहीं खींची जा रही है ... जैसे कि यह कमरे से बाहर निकलता है
RoundSparrow Hilltx

7
एक और चीज़। मुझे संदेह है कि tTextColor एक redraw मजबूर कर रहा है - जिसके कारण इस onDraw का अंतहीन लूप ओवर-ओवर कहलाता है। परीक्षण करते समय इस विधि में लॉगकट या अन्य संकेतक लगाने की सलाह दी जाती है।
राउंडस्पारो हिल्टैक्स

@ राउंडस्पैरोहिल्टेक्स सही है। जैसा कि मैंने एक और इसी तरह के उत्तर के लिए एक टिप्पणी में उल्लेख किया है, मुझे संदेह है कि इस कमी के चारों ओर एकमात्र तरीका है और TextViewअपनी खुद की कक्षा में संपूर्णता को चिपकाने के लिए निजी mCurTextColor क्षेत्र में सीधे पहुंचने के लिए प्रतिबिंब का उपयोग करना है TextViewयह उत्तर यह कैसे करना है की एक सामान्य दिशानिर्देश प्रदान करता है। यदि आप संकेत और लिंक पाठ को एक स्ट्रोक के रूप में अच्छी तरह से करना चाहते हैं, तो आपको भी बदलना होगा mHintTextColorऔर mLinkTextColor। दुर्भाग्य से बदलना mTextColorकुछ भी नहीं है, क्योंकि यह केवल संदर्भित है।
वेरुमच

विल लूप पर हमेशा के लिए
user924

8

मैंने रूपरेखा के साथ पाठ करने के लिए एक वर्ग लिखा है और अभी भी सामान्य पाठ दृश्य के अन्य सभी विशेषताओं और ड्राइंग का समर्थन करता हूं।

यह मूल रूप से उपयोग करता है super.onDraw(Canves canvas)पर TextViewलेकिन विभिन्न शैलियों के साथ दो बार खींचता है।

उम्मीद है की यह मदद करेगा।

public class TextViewOutline extends TextView {

    // constants
    private static final int DEFAULT_OUTLINE_SIZE = 0;
    private static final int DEFAULT_OUTLINE_COLOR = Color.TRANSPARENT;

    // data
    private int mOutlineSize;
    private int mOutlineColor;
    private int mTextColor;
    private float mShadowRadius;
    private float mShadowDx;
    private float mShadowDy;
    private int mShadowColor;

    public TextViewOutline(Context context) {
        this(context, null);
    }

    public TextViewOutline(Context context, AttributeSet attrs) {
        super(context, attrs);
        setAttributes(attrs);
    }

    private void setAttributes(AttributeSet attrs){ 
        // set defaults
        mOutlineSize = DEFAULT_OUTLINE_SIZE;
        mOutlineColor = DEFAULT_OUTLINE_COLOR;   
        // text color   
        mTextColor = getCurrentTextColor();
        if(attrs != null) {
            TypedArray a = getContext().obtainStyledAttributes(attrs,R.styleable.TextViewOutline);
            // outline size
            if (a.hasValue(R.styleable.TextViewOutline_outlineSize)) {
                mOutlineSize = (int) a.getDimension(R.styleable.TextViewOutline_outlineSize, DEFAULT_OUTLINE_SIZE);
            }
            // outline color
            if (a.hasValue(R.styleable.TextViewOutline_outlineColor)) {
                mOutlineColor = a.getColor(R.styleable.TextViewOutline_outlineColor, DEFAULT_OUTLINE_COLOR);
            }
            // shadow (the reason we take shadow from attributes is because we use API level 15 and only from 16 we have the get methods for the shadow attributes)
            if (a.hasValue(R.styleable.TextViewOutline_android_shadowRadius) 
                    || a.hasValue(R.styleable.TextViewOutline_android_shadowDx)
                    || a.hasValue(R.styleable.TextViewOutline_android_shadowDy) 
                    || a.hasValue(R.styleable.TextViewOutline_android_shadowColor)) {
                mShadowRadius = a.getFloat(R.styleable.TextViewOutline_android_shadowRadius, 0);
                mShadowDx = a.getFloat(R.styleable.TextViewOutline_android_shadowDx, 0);
                mShadowDy = a.getFloat(R.styleable.TextViewOutline_android_shadowDy, 0);
                mShadowColor = a.getColor(R.styleable.TextViewOutline_android_shadowColor, Color.TRANSPARENT);
            }

            a.recycle();
        }

        PFLog.d("mOutlineSize = " + mOutlineSize);
        PFLog.d("mOutlineColor = " + mOutlineColor);
    }

    private void setPaintToOutline(){
        Paint paint = getPaint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(mOutlineSize);
        super.setTextColor(mOutlineColor);
        super.setShadowLayer(mShadowRadius, mShadowDx, mShadowDy,  mShadowColor);
    }

    private void setPaintToRegular() {
        Paint paint = getPaint();
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeWidth(0);
        super.setTextColor(mTextColor);
        super.setShadowLayer(0, 0, 0, Color.TRANSPARENT);
    } 

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setPaintToOutline();
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    public void setTextColor(int color) {
        super.setTextColor(color);
        mTextColor = color;
    } 

    @Override
    public void setShadowLayer(float radius, float dx, float dy, int color) {
        super.setShadowLayer(radius, dx, dy, color);
        mShadowRadius = radius;
        mShadowDx = dx;
        mShadowDy = dy;
        mShadowColor = color;
    }

    public void setOutlineSize(int size){
        mOutlineSize = size;
    }

    public void setOutlineColor(int color){
       mOutlineColor = color;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        setPaintToOutline();
        super.onDraw(canvas);
        setPaintToRegular();
        super.onDraw(canvas);
    }

}

attr.xml

<declare-styleable name="TextViewOutline">
    <attr name="outlineSize" format="dimension"/>
    <attr name="outlineColor" format="color|reference"/>
    <attr name="android:shadowRadius"/>
    <attr name="android:shadowDx"/>
    <attr name="android:shadowDy"/>
    <attr name="android:shadowColor"/>
</declare-styleable>

टाइपराइरे पर a.recycle () गायब है
Leos लीटरक

5

आप इस कार्यक्रम को नीचे दिए गए स्निपेट के साथ कर सकते हैं। काली पृष्ठभूमि के साथ सफेद अक्षर प्रदान करता है:

textView.setTextColor(Color.WHITE);            
textView.setShadowLayer(1.6f,1.5f,1.3f,Color.BLACK);

विधि के पैरामीटर त्रिज्या, डीएक्स, डाई, रंग हैं। आप विशिष्ट आवश्यकताओं के लिए उन्हें बदल सकते हैं।

मुझे आशा है कि मैं किसी ऐसे व्यक्ति की मदद करूंगा जो TextView को प्रोग्रामेटिक रूप से बनाता है और इसे xml के अंदर नहीं करता है।

ढेर करने के लिए ढेर समुदाय!


2

मैंने कुछ परिवर्धन के साथ नौमान हनीफ के उत्तर पर आधारित एक पुस्तकालय बनाया है । उदाहरण के लिए, View.invalidate () कॉल पर एक अप्रत्यक्ष अनंत लूप के कारण बग को ठीक करना।

OTOH, लाइब्रेरी EditText विजेट में उल्लिखित पाठ का भी समर्थन करता है, क्योंकि यह मेरा वास्तविक लक्ष्य था और इसे TextView की तुलना में थोड़ा अधिक काम करने की आवश्यकता थी।

यहाँ मेरी लाइब्रेरी का लिंक है: https://github.com/biomorgoth/android-outline-textview

समाधान पर प्रारंभिक विचार के लिए नोमान हनीफ को धन्यवाद!


2

मैं प्रदर्शन के मुद्दे को हल करने के लिए एक समाधान जोड़ना चाहता हूं। उदाहरण के लिए, @YGHM और कुछ अन्य लोगों के इस सवाल का जवाब काम करता है, लेकिन इसके बारे में अनंत कॉल का कारण बनता है onDrawक्योंकि setTextColorकॉल invalidate()। तो इसे हल करने के लिए, आपको invalidate()एक चर को ओवरराइड करने और जोड़ने की ज़रूरत है isDrawingजिसे आप सेट करेंगे true, जब onDraw()प्रगति में है और एक स्ट्रोक के साथ ड्राइंग करें। यदि चर है तो अमान्य वापस आ जाएगा true

override fun invalidate() {
    if (isDrawing) return
    super.invalidate()
  }

आपका ऑनड्राइव इस तरह दिखेगा:

override fun onDraw(canvas: Canvas) {
    if (strokeWidth > 0) {
      isDrawing = true
      val textColor = textColors.defaultColor
      setTextColor(strokeColor)
      paint.strokeWidth = strokeWidth
      paint.style = Paint.Style.STROKE
      super.onDraw(canvas)
      setTextColor(textColor)
      paint.strokeWidth = 0f
      paint.style = Paint.Style.FILL
      isDrawing = false
      super.onDraw(canvas)
    } else {
      super.onDraw(canvas)
    }
  }

1

MagicTextView स्ट्रोक फॉन्ट बनाने के लिए बहुत उपयोगी है, लेकिन मेरे मामले में, यह इस तरह की त्रुटि का कारण बनता है, जो डुप्लिकेट पृष्ठभूमि विशेषताओं के कारण हुई यह त्रुटि है जो MagicTextView द्वारा सेट की गई है

इसलिए आपको attrs.xml और MagicTextView.java संपादित करने की आवश्यकता है

attrs.xml

<attr name="background" format="reference|color" /><attr name="mBackground" format="reference|color" />

MagicTextView.java 88:95

if (a.hasValue(R.styleable.MagicTextView_mBackground)) {
Drawable background = a.getDrawable(R.styleable.MagicTextView_mBackground);
if (background != null) {
    this.setBackgroundDrawable(background);
} else {
    this.setBackgroundColor(a.getColor(R.styleable.MagicTextView_mBackground, 0xff000000));
}
}

1

मुझे TextView से विरासत के बिना दृश्य को रेखांकित करने का सरल तरीका मिला । मैंने सरल पुस्तकालय लिखा था जो पाठ को रेखांकित करने के लिए Android के Spannable का उपयोग करता है। यह समाधान पाठ के केवल भाग को रेखांकित करने की संभावना देता है।

मैंने पहले से ही एक ही सवाल पर जवाब दिया था ( उत्तर )

वर्ग:

class OutlineSpan(
        @ColorInt private val strokeColor: Int,
        @Dimension private val strokeWidth: Float
): ReplacementSpan() {

    override fun getSize(
            paint: Paint,
            text: CharSequence,
            start: Int,
            end: Int,
            fm: Paint.FontMetricsInt?
    ): Int {
        return paint.measureText(text.toString().substring(start until end)).toInt()
    }


    override fun draw(
            canvas: Canvas,
            text: CharSequence,
            start: Int,
            end: Int,
            x: Float,
            top: Int,
            y: Int,
            bottom: Int,
            paint: Paint
    ) {
        val originTextColor = paint.color

        paint.apply {
            color = strokeColor
            style = Paint.Style.STROKE
            this.strokeWidth = this@OutlineSpan.strokeWidth
        }
        canvas.drawText(text, start, end, x, y.toFloat(), paint)

        paint.apply {
            color = originTextColor
            style = Paint.Style.FILL
        }
        canvas.drawText(text, start, end, x, y.toFloat(), paint)
    }

}

पुस्तकालय: रूपरेखा


1
यह बहु-पंक्ति पाठ का समर्थन नहीं करता है
उपयोगकर्ता 924

0

तो आप textview के चारों ओर एक स्ट्रोक चाहते हैं? दुर्भाग्य से स्टाइल के साथ ऐसा करने का कोई सरल तरीका नहीं है। आपको एक और दृश्य बनाना होगा और अपने टेक्स्टव्यू को ओवर-टॉप करना होगा, जिससे अभिभावक दृश्य (वह सबसे ऊपर है) बस कुछ पिक्सेल बड़ा हो जाता है - यह एक रूपरेखा बनाना चाहिए।


हम्म, कि यह दर्द की तुलना में अधिक दर्द की तरह लगता है। मुझे ध्यान है कि एक सफेद पृष्ठभूमि पर हरे रंग का पाठ पढ़ने योग्य है (अभी यह पढ़ने में कठिन है) img88.imageshack.us/i/devicez.png लाल ठीक दिखता है। शायद अगर मैं बस एक गहरे हरे रंग में बदल
जाऊं

क्या आप तब पाठ की रूपरेखा बनाने की कोशिश कर रहे हैं? यह वास्तव में संभव नहीं है, जब तक कि आप अपना स्वयं का कस्टम टेक्स्ट व्यू नहीं करते हैं, लेकिन यह संभवतः इसके लायक होने की तुलना में अधिक काम है। यह शायद केवल इसे गहरा हरा बनाने के लिए आसान है।
xil3

2
किसी ऐसे व्यक्ति से जो लाल / हरा रंग का है, से एक छोटा सा अनुरोध: कृपया उसी लाल / हरे रंग की जानकारी के वैकल्पिक प्रतिनिधित्व में जोड़ने पर विचार करें, क्योंकि गहरे हरे रंग को देखना बनाम गहरा लाल रंग हमारे लिए अक्सर कठिन होता है। शायद एक ऊपर / नीचे तीर भी?
स्टीव पोमेरॉय

यह एक अच्छी बात है स्टीव। मैं शायद भविष्य में इसे जोड़ूंगा।
फल्मरी जूल

0

यहाँ TextView का विस्तार करके मुझे सबसे आसान तरीका मिल सकता है

public class CustomTextView extends androidx.appcompat.widget.AppCompatTextView {

float mStroke;

public CustomTextView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.obtainStyledAttributes(attrs,
            R.styleable.CustomTextView);
    mStroke=a.getFloat(R.styleable.CustomTextView_stroke,1.0f);
    a.recycle();
}

@Override
protected void onDraw(Canvas canvas) {
    TextPaint paint = this.getPaint();
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(mStroke);
    
    super.onDraw(canvas);
}
}

तब आपको केवल attrs.xml फ़ाइल में निम्न जोड़ना होगा

<declare-styleable name="CustomTextView">
    <attr name="stroke" format="float"/>
</declare-styleable>

और अब आप TextView के app:strokeअन्य सभी वांछनीय गुणों को बरकरार रखते हुए स्ट्रोक विधा को स्थापित करने में सक्षम होंगे । मेरा समाधान केवल स्ट्रोक w / oa भराव खींचता है। यह दूसरों की तुलना में थोड़ा सरल बनाता है। मेरे कस्टमटेक्स्टव्यू के लिए एक कस्टम फॉन्ट सेट करते समय परिणाम के साथ एक स्क्रेंप्चर करें।

यहां छवि विवरण दर्ज करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.