2011-09-30 12 views
14

Al seguente linkFont nella libreria Android

Android Dev Guide

è scrivere:

progetti di libreria non possono includere attività prime Gli strumenti non supportano l'utilizzo di file di asset prime (salvato nel patrimonio/directory) in un progetto di libreria. Qualsiasi risorsa risorse utilizzata da un'applicazione deve essere memorizzata nella cartella assets/del progetto dell'applicazione stesso. Tuttavia, i file di risorse salvati nella directory res/sono supportati.

Quindi, se voglio creare un componente di visualizzazione personalizzato che utilizza un carattere personalizzato, come posso accedere alla risorsa? Non posso ridistribuire il mio componente con il mio font preferito !!!!

migliori saluti

+0

Quello che dice è che una libreria non può contenere risorse, è necessaria un'applicazione per archiviare le risorse. –

+0

Provare a inserirli nella cartella res/raw e recuperarli da R.raw.somefile –

+0

ok Lo so, ma non ho un'applicazione nel mio livrary, solo un'estensione View – Mr32Bit

risposta

7

Ok ho trovato una soluzione per il problema. È necessario copiare il file in una directory esterna, quindi caricare un carattere dal file con Typeface.createFromFile e quindi eliminare il file temporaneo. So che non è una modalità di lavoro pulita ma è una grata funzionante.

1 - è necessario mettere il tipo di carattere su "/res/raw/font.ttf"

2 - Inser nel codice il seguente metodo

3 - mettere nel codice Typeface mFont = FileStreamTypeface(R.raw.font);

4 - Tutto è fatto

Typeface FileStreamTypeface(int resource) 
{ 
    Typeface tf = null; 

    InputStream is = getResources().openRawResource(resource); 
    String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/gmg_underground_tmp"; 
    File f = new File(path); 
    if (!f.exists()) 
    { 
     if (!f.mkdirs()) 
      return null; 
    } 

    String outPath = path + "/tmp.raw"; 

    try 
    { 
     byte[] buffer = new byte[is.available()]; 
     BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outPath)); 

     int l = 0; 
     while((l = is.read(buffer)) > 0) 
     { 
      bos.write(buffer, 0, l); 
     } 
     bos.close(); 

     tf = Typeface.createFromFile(outPath); 

     File f2 = new File(outPath); 
     f2.delete(); 
    } 
    catch (IOException e) 
    { 
     return null; 
    } 

    return tf;  
} 

se qualcuno ha un'alternativa sono contento di leggerlo. Avete ricordare che questa soluzione è solo per Android biblioteche

Cordiali saluti

+0

dove scrivere questo metodo? il metodo getResources() non è disponibile nella mia classe. – khizar

0

Quindi, se voglio creare un componente visualizzazione personalizzata che utilizzano un carattere personalizzato come posso accedere alla risorsa?

Il tuo codice sarebbe accedere allo stesso modo che non è così. Dovrai semplicemente comunicare ai reuser della tua vista personalizzata di includere il file di font nelle loro risorse.

Non riesco a ridistribuire il mio componente con il mio font preferito !!!!

Certo che puoi. Metti il ​​carattere in un file ZIP insieme al resto del progetto della tua biblioteca, insieme alle istruzioni su dove metterlo in un progetto. Assicurati di utilizzare un font che hai i diritti di ridistribuire in questo modo, però.

+0

Distribuire risorse a parte, è qualcosa in realtà Non mi piace fare. Nel mio caso, quindi, ho rinunciato allo sviluppo della funzionalità. I font, come le bitmap immagine, dovrebbero essere in grado di essere caricati, almeno, da un InputStream. Risolverà molti problemi e renderà il codice nelle librerie più organizzato e pulito, le integrazioni più semplici e le risorse della biblioteca non confuse con il progetto finale. – Lisitso

+0

@Lisitso: "I caratteri, come le immagini bitmap, dovrebbero essere in grado di essere caricati -almeno- da un InputStream" - non avrai argomenti da parte mia. Sebbene si noti che il pacchetto AAR per i progetti di libreria Android aiuterà alcuni con il problema originale dell'OP. – CommonsWare

+0

Hi CommonsWare, sfortunatamente non ho capito il contenuto della risposta (pacchetto AAR? Problema originale di OP?) Ma grazie comunque. – Lisitso

24

Ecco un metodo per i font di carico dalle risorse che funziona davvero ;-) credito al mr32bit per la prima versione.

private Typeface getFontFromRes(int resource) 
{ 
    Typeface tf = null; 
    InputStream is = null; 
    try { 
     is = getResources().openRawResource(resource); 
    } 
    catch(NotFoundException e) { 
     Log.e(TAG, "Could not find font in resources!"); 
    } 

    String outPath = getCacheDir() + "/tmp" + System.currentTimeMillis() ".raw"; 

    try 
    { 
     byte[] buffer = new byte[is.available()]; 
     BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outPath)); 

     int l = 0; 
     while((l = is.read(buffer)) > 0) 
      bos.write(buffer, 0, l); 

     bos.close(); 

     tf = Typeface.createFromFile(outPath); 

     // clean up 
     new File(outPath).delete(); 
    } 
    catch (IOException e) 
    { 
     Log.e(TAG, "Error reading in font!"); 
     return null; 
    } 

    Log.d(TAG, "Successfully loaded font."); 

    return tf;  
} 
+1

Questa dovrebbe essere la risposta accettata. – DiscDev

+0

Questa non può essere la risposta accettata! Ciò potrebbe causare un problema su alcuni dispositivi (ad esempio Motorola Razr). Se carichi due tipi di carattere diversi, potrebbe essere lo stesso oggetto! –

+1

aggiunto una correzione sopra ... (y) –

2

IntelliJ IDEA (e Android Studio come si basa su IntelliJ) ha una funzione che permette di includere i file di risorse del modulo di libreria al modulo applicativo, non so su altri ambienti.

Passare alla struttura del progetto nel menu file, quindi sfaccettature, selezionare il modulo dell'applicazione, nella scheda del compilatore selezionare la casella di controllo "include risorse da dipendenze nell'APK".

Poiché intellij è molto meglio di Eclipse, penso che la migrazione sia ragionevole.

EDIT:

Asset e la fusione manifesti sono pienamente supportati in studio Android.

0

Anche se hai messo i tuoi font nella cartella assets/fonts, in qualche modo questa libreria funziona ed è molto facile da usare: https://github.com/neopixl/PixlUI. L'ho provato con successo su Android 2.3. così come 4.4

0

basta usare la risposta di @ bk138 con questo piccolo cambiamento che funziona per me

aggiungere questo nel manifesto

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 

e aggiungere questo prima di creare il Buffered

 File f2 = new File(outPath); 
     BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outPath)); 
0

Il codice seguente modifica la soluzione da @ bk138 e include i consigli di @Jason Robinson per la mancata eliminazione del file e il controllo di un pre prima vivamente il file memorizzato nella cache. Inoltre, denomina il file temporaneo dopo il carattere anziché il tempo creato.

public static Typeface getFontFromRes(Context context, int resId, boolean deleteAfterwards){ 
    String tag = "StorageUtils.getFontFromRes"; 

    String resEntryName = context.getResources().getResourceEntryName(resId); 
    String outPath = context.getCacheDir() + "/tmp_" + resEntryName + ".raw"; 

    //First see if the file already exists in the cachDir 
    FileInputStream fis = null; 
    try { 
     fis = new FileInputStream(new File(outPath)); 
    } catch (FileNotFoundException e) { 
     Log.d(tag,"fileNotFoundException outPath:"+outPath+e.getMessage()); 
    } 

    if(fis != null){    
     try { 
      Log.d(tag,"found cached fontName:"+resEntryName); 
      fis.close(); 
     } catch (IOException e) { 
      Log.d(tag,"IOException outPath:"+outPath+e.getMessage()); 
     } 

     //File is already cached so return it now 
     return Typeface.createFromFile(outPath); 
    }  

    InputStream is = null; 
    try { 
     is = context.getResources().openRawResource(resId); 
    }catch(NotFoundException e) { 
     Log.e(tag, "Could not find font in resources! " + outPath); 
    } 

    try{ 
     byte[] buffer = new byte[is.available()]; 
     BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outPath)); 

     int l = 0; 
     while((l = is.read(buffer)) > 0) 
      bos.write(buffer, 0, l); 

     bos.close(); 
    }catch (IOException e){ 
     Log.e(tag, "Error reading in font!"); 
     return null; 
    }   

    Typeface tf = Typeface.createFromFile(outPath); 

    if(deleteAfterwards){ 
     // clean up if desired 
     new File(outPath).delete(); 
    } 

    Log.d(tag, "Successfully loaded font."); 

    return tf;  
} 
1

Se si estende un TextView e si desidera utilizzare molte di queste vedute si dovrebbe avere una sola istanza del carattere tipografico in questa vista. Copiare il file .ttf * in res/raw/e utilizzando il seguente codice:

public class MyTextView extends TextView { 
    public static final String FONT = "font.ttf"; 
    private static Typeface mFont; 

    private static Typeface getTypefaceFromFile(Context context) { 
     if(mFont == null) { 
      File font = new File(context.getFilesDir(), FONT); 
      if (!font.exists()) { 
       copyFontToInternalStorage(context, font); 
      } 
      mFont = Typeface.createFromFile(font); 
     } 
     return mFont; 
    } 

    private static void copyFontToInternalStorage(Context context, File font) { 
     try { 
      InputStream is = context.getResources().openRawResource(R.raw.font); 
      byte[] buffer = new byte[4096]; 
      BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(font)); 
      int readByte; 
      while ((readByte = is.read(buffer)) > 0) { 
       bos.write(buffer, 0, readByte); 
      } 
      bos.close(); 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public MyTextView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     setTypeface(getTypefaceFromFile(context)); 
    } 
} 

mFont è una variabile statica, quindi il riferimento non viene distrutto e può essere riutilizzato in altre MyTextViews. Questo codice è quasi uguale alle altre risposte ma immagino che sia efficiente e consuma meno memoria se lo si utilizza in un ListView o qualcosa del genere.

0

Ecco la mia versione modificata/miglioramento sulla risposta di @ Mr32Bit. Alla prima chiamata, copio il carattere nella directory privata dell'app/custom_fonts. Le future letture controllano se esiste e se così legge la copia esistente (risparmia tempo sul file di coping ogni volta).

nota: Questo presuppone solo un singolo carattere personalizzato.

/** 
    * Helper method to load (and cache font in app private folder) typeface from raw dir this is needed because /assets from library projects are not merged in Eclipse 
    * @param c 
    * @param resource ID of the font.ttf in /raw 
    * @return 
    */ 
    public static Typeface loadTypefaceFromRaw(Context c, int resource) 
    { 
     Typeface tf = null; 

     InputStream is = c.getResources().openRawResource(resource); 
     String path = c.getFilesDir() + "/custom_fonts"; 
     File f = new File(path); 
     if (!f.exists()) 
     { 
      if (!f.mkdirs()) 
       return null; 
     } 

     String outPath = path + "/myfont.ttf"; 

     File fontFile = new File(outPath); 
     if (fontFile.exists()) { 
      tf = Typeface.createFromFile(fontFile); 
     }else{ 
      try 
      { 
       byte[] buffer = new byte[is.available()]; 
       BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outPath)); 
       int l = 0; 
       while((l = is.read(buffer)) > 0) 
       { 
        bos.write(buffer, 0, l); 
       } 
       bos.close(); 
       tf = Typeface.createFromFile(outPath); 
      } 
      catch (IOException e) 
      { 
       return null; 
      } 
     } 
     return tf; 
    }