Android Hintergrundfarbe von Textview (Shape) ändern

IceTi

Bekanntes Mitglied
Hallo Leute,

ich bin z.Z. dabei ein Widget zu entwickeln.
Nun möchte ich dem Nutzer die Möglichkeit bieten die Hintergrundfabe des Widgets ändern zu können.

Das Layout des Widgets ist wie folgt aufgebaut:

Code:
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="horizontal" 
    android:padding="@dimen/widget_margin" >
              
    <TextView
        android:id="@+id/update"
        style="@android:style/TextAppearance.Small"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/myshape"
        android:gravity="center_horizontal|center_vertical"
        android:text="Test"
        android:textColor="#ffffff" />
    
</LinearLayout>

Der Hintergrund des Textviews wird also mit einem Shape festgelegt:

Code:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle" >

    <stroke android:width="1dp"
        	android:color="#FFFFFFFF" />

    <solid android:color="#AA154e72" />

    <corners android:bottomLeftRadius="7dp"
        	 android:bottomRightRadius="7dp"
        	 android:topLeftRadius="7dp"
        	 android:topRightRadius="7dp" />
</shape>


Nun wie kann ich die Hintergrundfarbe des Shapes während der Laufzeit ändern? Ich habe schon Stundenlang gegoogled aber nichts gefunden. Hat damit vll einer Erfahrungen?

Danke
 

schlingel

Gesperrter Benutzer
Je nach dem was du möchtest gibt's 3 Möglichkeiten:

- setBackgroundColor - setzt, wie der Name schon sagt, die Hintergrundfarbe.
- setBackgroundDrawable Wenn du zur Laufzeit ein neues Bild erstellst/herunterlädst, kannst du mittels dieser Methode den Hintergrund neu setzen. Damit wäre es möglich, wenn du das ShapeDrawable zur Laufzeit erstellst.
- setBackgroundResource - Wenn du eine statische Resource hast, die du zur Laufzeit setzen möchtest kannst du hier mit dem üblichen R.drawable.deineID arbeiten. Damit wäre es möglich, wenn du zwei verschiedene XMLs hast.

Rein aus Interesse, nach was hast du gesucht und hast du vorher schon die Doku von TextView gelesen? Das hilft vielleicht, wenn ich mal einen Artikel schreibe um die richtigen Schlagwörter dafür zu finden.
 
Zuletzt bearbeitet:

IceTi

Bekanntes Mitglied
Hmm, glaube sowas in die Richtung hatte ich schon probiert... Also z.Z. geife ich via "RemoteViews" auf das TextView zu um z.B. die Größe oder die Schriftfarbe zu ändern... Auf ein Textview, welches ein Widget benutzt, kann ich so einfach nicht zugreifen oder??? Sondern nur auf das Layout welches in "onCreate" erstellt wurde... oder sehe ich das falsch?
 

schlingel

Gesperrter Benutzer
OK, wenn du das per RemoteView erledigst, ist das natürlich eine andere Situation. Wie weit kannst du denn den zweiten Prozess beeinflussen?

Im schlimmsten Fall, musst du dir in diesem Prozess/Thread ne Methode schreiben die, die lokale Methode an der TextView aufruft.

Wofür brauchst du denn die RemoteView?
 

IceTi

Bekanntes Mitglied
Also ich aktualisiere die Widgets via Touch und dann wird ein entsprechender Service gestartet... Wie gesagt, mit den RemoteViews ändere ich den Textgröße und/oder die Farbe sowie den Text ansich...
 

schlingel

Gesperrter Benutzer
Aus dem Service änderst du deine Activity. Da stellt sich zu erst einmal die Frage warum die UI so eng an den Service gekoppelt werden muss und zum anderen was genau der Service tut und warum der Service nicht eine definierte Methode in der Activity anstößt die dann wieder dort im UI-Thread die nötigen Änderungen erledigt.
 

IceTi

Bekanntes Mitglied
Ne, die Activity hat ja nichts mit dem Service zu tun... Die Widgets bzw. der jeweilige WidgetProvider startet den Service...

Ich glaube wir reden grad aneinander vorbei, oder? ;-)
 

schlingel

Gesperrter Benutzer
Am besten ist es wohl du zeigst mal ein wenig Code her. Was erzeugt was, wer ruft was auf. Wo klappt ein Aufruf von dir nicht.

Ansonsten bleibt das ein Herumstochern im Dunkeln.
 

IceTi

Bekanntes Mitglied
So, also mein Widget-Layout sieht wie folgt aus:

[XML]
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:eek:rientation="horizontal"
android:padding="@dimen/widget_margin" >
<TextView
android:id="@+id/update"
style="@android:style/TextAppearance.Small"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/myshape"
android:gravity="center_horizontal|center_vertical"
android:text="Test"
android:textColor="#ffffff" />
</LinearLayout>
[/XML]

Der Hintergrund wird wie gesagt mittels des Shape generiert:
[XML]
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >

<stroke android:width="1dp"
android:color="#FFFFFFFF" />

<solid android:color="#AA154e72" />

<corners android:bottomLeftRadius="7dp"
android:bottomRightRadius="7dp"
android:topLeftRadius="7dp"
android:topRightRadius="7dp" />
</shape
[/XML]


Meine Activity (Main.java), also die App an sich, ist nur zum Konfigurieren der Widgets Zuständig (Textfarbe, Textgröße und noch andere Einstellungen).
Beim "klicken" auf ein Widget wird der entsprechende WidgetProvider aufgerufen, welcher dann einen Service startet:

Java:
public class WidgetProviderTest extends AppWidgetProvider {
	
	@Override
	public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
		// Intent erzeugen und Service starten
		Intent intent = new Intent(context.getApplicationContext(), UpdateWidgetService.class);
		context.startService(intent);
	}
}


Im Service selber wird der Text des Widgets dann aktualisiert. Hier werden dann auch die Einstellungen wie Textgröße etc. noch einmal gesetzt, falls diese in der App geändert wurden:
Java:
...
remoteView = new RemoteViews(this.getApplicationContext().getPackageName(), R.layout.widget_layout_test;

remoteView.setTextViewText(R.id.update, text);
remoteView.setTextColor(R.id.update, Color.argb(a, r, g, b));
remoteView.setFloat(R.id.update, "setTextSize", config.getTxtSize());
			
appWidgetManager.updateAppWidget(widgetId, remoteView);
...

In diesem Schritt würde ich nun gerne auch den Hintergrund ändern. Nur das bekomme ich halt nicht hin, da ich im Service nur über RemoteViews auf das TextView vom Widget zugreifen kann, oder?

Hoffe nun wird mein Problem klarer. Im Endeffekt möchte ich dem Benutzer die Möglichkeit bieten den hintergrund der Widgets ändern zu können und wenn der Hintergrund einmal eingestellt ist, soll mein beim Neuanlegen eines Widgets nicht die App starten müssen, dies soll dann automatisch geändert werden, da das neue Widget ja erstmal mit den Standard Werten aus dem Shape arbeiten.

Danke schon einmal!
 

schlingel

Gesperrter Benutzer
Also außer dass du mit

Java:
remoteView.setInt(R.id.viewid, "setBackgroundColor", getResources().getColor(R.color.deineFarbe));

dein Glück probierst oder eine eigene Shape mit der richtigen Farbe anlegst und die dann tauscht fällt mir nichts ein. Das ganze ist mit dem WidgetProvider sehr vertrakt. Am Anfang dachte ich, du sprichst von einer normalen Activity aber die API ist im Bezug auf Widgets ziemlich kastriert.
 

IceTi

Bekanntes Mitglied
Also das mit dem "setInt" habe schon versicht, funktioniert an sich (die Farbe ändert sich) aber dann wird der Hintergrund vom TextView geändert und das Shape Dingen komplett überschrieben (nicht mehr sichtbar).

Son Shape anlegen und austauschen funtkioniert iwie auch nicht bzw. habe ich es nicht hinbekommen... Hmm... Gibt es vll einen komplette anderen Weg?

Danke
 

schlingel

Gesperrter Benutzer
Nein, etwas anderes fällt mir nicht ein. Aber das Setzen einer neuen Hintergroundresource sollte funktionieren.

Was passiert denn bei dir? Gibt's eine Exception oder tut sich einfach gar nichts?
 

IceTi

Bekanntes Mitglied
So, also mit

Java:
remoteView.setInt(R.id.update,"setBackgroundResource",R.drawable.myshape2);

kann ich nun das Shape ändern... nun muss ich nun für alle Farben ein eigenes Shape anlegen und somit ist das ganze nicht soooo dynamisch wie ich es gerne hätte... Kann ich das EINE Shape iwie direkt verändern oder selber im code ein anlegen?

Danke
 
Zuletzt bearbeitet:

schlingel

Gesperrter Benutzer
Hm, nicht so einfach aber möglich.

1. Du kreierst deine ShapeDrawable wie es hier beschrieben ist.
2. Du erzeugst ein Canvas-Objekt und daraus ein Bitmap-Objekt wie es hier beschrieben ist und läßt deine DrawableShape per draw in's Canvas-Objekt zeichnen.
3. Dein Bitmap-Objekt kannst du jetzt per setBitmap setzen.

Äußerst umständlich, aber das ist im Moment das einzige was mir einfällt.
 

IceTi

Bekanntes Mitglied
Scheint mir auch recht umständlich...

Ich lasse es erstmal so mit den verschiedenen Layout-Dateien.

Was anderes fällt mir grad noch ein? Ist denn möglich die Padding- Eigentschaften während der Laufzeit zu ändern bzw. die Textausrichtung (links, rechts, mitte)?
 

schlingel

Gesperrter Benutzer
Testausrichtung sollte kein Problem sein, da die Eigenschaften Ints sind. Bei Padding schaut's schlecht aus. Dazu hab ich nichts gesehen.
 

IceTi

Bekanntes Mitglied
Hi,

also noch einmal zur Hintergrundgeschichte. Folgendes habe ich nun geschafft, und der Hintergrund wird auch gesetzt:

Java:
		    		Bitmap bitmap = Bitmap.createBitmap(200, 100, Bitmap.Config.ARGB_8888);
		    		Canvas canvas = new Canvas(bitmap);
		    		Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		    		mPaint.setColor(0xFFFF0000);
		    		canvas.drawRect(0, 0, 110, 140, mPaint);
//		    		canvas.drawCircle(0, 0, 50, mPaint);
		  
		    		remoteView.setBitmap(R.id.ImageViewMin, "setImageBitmap", bitmap);


Nur leider weiß ich nicht wie ich das Rechteckt ausrichten kann? Es erscheint teilweise nur halb oder so... Kann ich iwie die Größe des Widgets bzw. ImageViews auslesen?
Mittels "findViewById" geht es natürlich nicht, da es ein Widget Layout ist... Danke!
 

Oben