2017-08-25 18 views
0

我有一個帶單位表的SQLite數據庫。單位表被設置爲僅與兩列:預先設計一個Spinner選項中子字符串的顏色[Android Studio]

create table units (_id INTEGER PRIMARY KEY, desc TEXT) 

實施例數據在這個表中的行是:

  • _id:4
  • 遞減: 「螺旋#5 [2231]」

「[2231]」子字符串很重要,我想將其顏色更改爲中等灰色。 Id也喜歡對desc列中的數據執行此操作,而不是使用java操作它。

所以,我查詢數據:

/** 
* Get all unit records for display in spinner 
*/ 
public Cursor getAllUnitRecords(){ 
    String sql = "select * from units order by `desc`"; 
    return db.rawQuery(sql, null); 
} 

我的微調是這樣的:

<Spinner 
    android:id="@+id/UnitSpinner" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:spinnerMode="dropdown" /> 

而且我得到的數據,以微調這樣的:

// Prepare unit dropdown 
Cursor units = db.getAllUnitRecords(); 
MatrixCursor unitsMatrixCursor = new MatrixCursor(new String[] { "_id", "desc" }); 
unitsMatrixCursor.addRow(new Object[] { 0, "" }); 
MergeCursor unitsMergeCursor = new MergeCursor(new Cursor[] { unitsMatrixCursor, units }); 
String[] unitsFrom = new String[]{"desc"}; 
int[] unitsTo = new int[]{android.R.id.text1}; 
Spinner unitSpinner = (Spinner) findViewById(R.id.UnitSpinner); 
SimpleCursorAdapter unitAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_spinner_dropdown_item, unitsMergeCursor, unitsFrom, unitsTo, 0); 
unitAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
unitSpinner.setAdapter(unitAdapter); 

由於我想爲中間灰色的「[2231]」子字符串着色,所以我想我可能能夠更改數據中的desc值基地,所以它看起來像這樣:

"Helix #5 <font color='#6e737e'>[2231]</font>" 

我這樣做只是因爲我在搜索互聯網,它似乎可能工作。那麼,這是行不通的,因爲標籤只是輸出,而不是改變顏色。什麼是錯的,我該如何解決?我想如果有必要,我可以開放不同的解決方案,但是這個Android的東西對我來說很難,因爲我不經常使用它,所以我試圖去尋求最簡單的解決方案。

更新#1 ----------------------

所以@MartinMarconcini還跟點我在正確的方向,我複製並將他的colorSpan方法粘貼到我的活動類中進行測試。然後,我查看了堆棧溢出的所有線索,以瞭解如何修改我的微調器文本,然後如何修改SimpleCursorAdapter中的文本。

,我發現這些問題的答案:

這給了我一些想法,所以我試圖與工作:

// Prepare unit dropdown 
Cursor units = db.getAllUnitRecords(); 
MatrixCursor unitsMatrixCursor = new MatrixCursor(new String[] { "_id", "desc" }); 
unitsMatrixCursor.addRow(new Object[] { 0, "" }); 
MergeCursor unitsMergeCursor = new MergeCursor(new Cursor[] { unitsMatrixCursor, units }); 
String[] unitsFrom = new String[]{"desc"}; 
int[] unitsTo = new int[]{android.R.id.text1}; 
Spinner unitSpinner = (Spinner) findViewById(R.id.UnitSpinner); 
SimpleCursorAdapter unitAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_spinner_dropdown_item, unitsMergeCursor, unitsFrom, unitsTo, 0); 
unitAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 

/* NEW CODE STARTS HERE */ 
unitAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() { 

    public boolean setViewValue(View aView, Cursor aCursor, int aColumnIndex) { 

     if (aColumnIndex == 1) { 
      String desc = aCursor.getString(aColumnIndex); 
      TextView textView = (TextView) aView; 
      final Spannable colorized = colorSpan(desc); 
      textView.setText(TextUtils.isEmpty(colorized) ? desc + "a" : colorized + "b"); 
      return true; 
     } 

     return false; 
    } 
}); 
/* NEW CODE ENDS HERE */ 

unitSpinner.setAdapter(unitAdapter); 

公告如果沒有文本,我添加了字母「a」,如果有的話,我添加了「b」文本。果然,「a」和「b」被添加到我的微調項目中,但沒有顏色變化!所以,我正在嘗試...但仍可以使用一些幫助。這是我所看到的圖像:

Screenshot of Android Phone

+0

[設置TextView跨度在Android中的顏色]可能的重複(https://stackoverflow.com/questions/3282940/set-color-of-textview-span-in-android) –

+0

這個問題與無關TextViews。 –

+0

textView是_irrelevant_,問題是關於「着色字符串」。這是用Spannables完成的。這個問題會引導你。 –

回答

1

正如在評論中提到的,呈現不應該依賴於邏輯。這是一個演示問題。你想要顯示一個文本,並且你希望文本的一部分被着色。

所以,在你的應用程序的任何地方,你需要顯示/目前這段文字給用戶,說...

someTextViewOrOtherWidget.setText(yourString);

...你會那麼必須調用,它的顏色爲你的方法。

例...

我這個代碼轉移到一個單獨的方法/地方重用,使其更重用通過不硬編碼[]和這樣的,但是這是一個簡單的例子是什麼樣子:

private Spannable colorSpan(final String text) { 
    if (TextUtils.isEmpty(text)) { 
     // can't colorize an empty text 
     return null; 
    } 

    // Determine where the [] are. 
    int start = text.indexOf("["); 
    int end = text.indexOf("]"); 

    if (start < 0 || end < 0 || end < start) { 
     // can't find the brackets, can't determine where to colorize. 
     return null; 
    } 

    Spannable spannable = new SpannableString(text); 

    spannable.setSpan(
      new ForegroundColorSpan(Color.BLUE) 
      , start 
      , end 
      , Spannable.SPAN_EXCLUSIVE_EXCLUSIVE 
    ); 

    return spannable; 
} 

而且你會用它喜歡...

String text = "Hello [123123] how are you?"; 
    final Spannable colorized = colorSpan(text); 

    textView.setText(TextUtils.isEmpty(colorized) ? text : colorized); 

我希望這給你一個更好的主意如何開始。

+0

我已經做了我可以做的事,並且您的回答很有幫助,我仍然無法着色該文本,我更新了我的問題以及我所做的和結果的屏幕截圖,看起來它應該有效,但事實並非如此 –

+0

我看到...只是爲了(因爲我避難')請確定,你是否試過TextView看起來有顏色?只需添加一個簡單的文本視圖並查看它是否以顏色顯示。我想排除這對於Spinner尤其不是問題。認爲它是,紡紗工是......奇怪) –

+1

我會r回報。在交通變得瘋狂之前,我必須騎上我的自行車回家...... –

0

因此,在@MartinMarconcini的幫助下,我終於完成了需要完成的任務,因此我想在這裏留下「答案」,以防其他人想看看需要做什麼。我最終創建了一個自定義的遊標適配器,雖然我仍然對Android Studio的複雜性感到驚訝,但它的工作原理!

首先,在活動中,使用SimpleCursorAdapter的方式最終變成了自定義遊標適配器(它擴展了SimpleCursorAdapter)。

這些行:

Spinner unitSpinner = (Spinner) findViewById(R.id.UnitSpinner); 
SimpleCursorAdapter unitAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_spinner_dropdown_item, unitsMergeCursor, unitsFrom, unitsTo, 0); 
unitAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
unitSpinner.setAdapter(unitAdapter); 

被替換這些行:

Spinner customUnitSpinner = (Spinner) findViewById(R.id.UnitSpinner); 
UnitSpinnerCursorAdapter customUnitAdapter = new UnitSpinnerCursorAdapter(this, R.layout.unit_spinner_entry, unitsMergeCursor, unitsFrom, unitsTo, 0); 
customUnitSpinner.setAdapter(customUnitAdapter); 

我把自定義光標適配器在它自己的文件,我現在把馬丁的COLORSPAN方法有太多(對):

package android.skunkbad.xxx; 

import android.content.Context; 
import android.database.Cursor; 
import android.graphics.Color; 
import android.support.v4.widget.SimpleCursorAdapter; 
import android.text.Spannable; 
import android.text.SpannableString; 
import android.text.TextUtils; 
import android.text.style.ForegroundColorSpan; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.TextView; 

public class UnitSpinnerCursorAdapter extends SimpleCursorAdapter { 

    private Context context; 
    private int layout; 

    public UnitSpinnerCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) { 

     super(context, layout, c, from, to, flags); 
     this.context = context; 
     this.layout = layout; 

    } 

    /** 
    * newView knows how to return a new spinner option that doesn't contain data yet 
    */ 
    @Override 
    public View newView(Context context, Cursor cursor, ViewGroup parent) { 
     super.newView(context, cursor, parent); 

     Cursor c = getCursor(); 

     final LayoutInflater inflater = LayoutInflater.from(context); 
     View v = inflater.inflate(layout, parent, false); 

     int descCol = c.getColumnIndex("desc"); 
     String desc = c.getString(descCol); 
     final Spannable colorized = colorSpan(desc); 

     TextView unit_spinner_entry = (TextView) v.findViewById(R.id.custom_spinner_entry_desc); 

     if (unit_spinner_entry != null) { 
      unit_spinner_entry.setText(TextUtils.isEmpty(colorized) ? desc : colorized); 
     } 

     return v; 
    } 

    /** 
    * bindView knows how to take an existing layout and update it with the data pointed to by the cursor 
    */ 
    @Override 
    public void bindView(View view, Context context, Cursor cursor) { 
     super.bindView(view, context, cursor); 

     int descCol = cursor.getColumnIndex("desc"); 
     String desc = cursor.getString(descCol); 
     final Spannable colorized = colorSpan(desc); 

     TextView unit_spinner_entry = (TextView) view.findViewById(R.id.custom_spinner_entry_desc); 

     if (unit_spinner_entry != null) { 
      unit_spinner_entry.setText(TextUtils.isEmpty(colorized) ? desc : colorized); 
     } 

    } 

    private Spannable colorSpan(final String text) { 
     if (TextUtils.isEmpty(text)) { 
      // can't colorize an empty text 
      return null; 
     } 

     // Determine where the [] are. 
     int start = text.indexOf("["); 
     int end = text.indexOf("]"); 

     if (start < 0 || end < 0 || end < start) { 
      // can't find the brackets, can't determine where to colorize. 
      return null; 
     } 

     end++; /* Why do we even need this ? */ 

     Spannable spannable = new SpannableString(text); 

     spannable.setSpan(
       new ForegroundColorSpan(Color.rgb(100,100,100)) 
       , start 
       , end 
       , Spannable.SPAN_EXCLUSIVE_EXCLUSIVE 
     ); 

     return spannable; 
    } 

} 

最後,我必須爲微調器中的每個條目製作一個佈局文件:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="match_parent" 
    android:layout_height="50dp"> 


    <TextView 
     android:id="@+id/custom_spinner_entry_desc" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:textSize="16dp" 
     android:textColor="#FFFFFF" 
     android:layout_marginLeft="10dp" /> 

</LinearLayout> 

謝謝馬丁!這對你來說可能看起來沒有什麼,但對我來說很難,如果沒有你的幫助,我不可能做到。

其中一個注意事項:我必須在您的colorSpan方法中放入end++;,因爲由於某種原因,它沒有爲關閉括號着色。

+0

布萊恩幹得好!很好的實施。一些評論。 '結束++;/*爲什麼我們甚至需要這個? * /'。 - >你需要這個,因爲我的代碼有* bug *並且你修正了它;)('indexOf'返回第一個出現的字符出現的索引,在字符串012 [4] 6中,右括號的索引將會是5,想象這些值是用逗號分隔的:0,1,2,[,4,],6現在計算你需要達到你的角色的逗號;)因此你的最終+1對於跨度來說是好的,否則它是不包含。 –

+0

額外的評論是:儘量不要使用像PHP這樣的變量名('where_everything_is_named_like_this'),它不會明顯影響你的代碼,它是無關緊要的,但是......當你與Android/Java社區共享人員時,一定程度的一致性是首選(如果有的話,因爲它使事情變得更容易閱讀)。所以,習慣於按cmd + option-L(來格式化你的文件)並使用'camelCaseForVariables';)使它更容易平易近人。你也可以隨機使用final,甚至通常不需要(並且不再提供性能改進),所以最好保持一致... –

+0

因此,您可以在所有局部變量/參數(在適當情況下)使用它,或者你完全跳過它。 (最終意味着REFERENCE不能改變)。另外,把'end ++'直接放在'setSpan('方法中,你不需要增加它。最後但並非最不重要的,我建議你使用'layout_marginStart'(不是左邊)和'... end',而不是好的,這是一個適合國際化的版本(如果你需要使用RTL語言);)無論如何。做好工作,保持良好的工作。別擔心,我沒有使用SimpleCursorAdapter的時代,你刷新了我的mem,大事! –

相關問題