English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
现在手机上的悬浮窗应用越来越多,对用户来说,最常见的悬浮窗应用就是安全软件的悬浮小控件,拿360卫士来说,当开启悬浮窗时,它是一个小球,小球可以拖动,当点击小球出现大窗体控件,可以进行进一步的操作如:释放手机内存等等。于是借着慕课网的视频,仿着实现了360加速球,增加了点击小球进行释放内存的功能。
由于是手机只有频幕截图:实现后如下图所示:点击开启按钮,出现悬浮窗小球控件上面显示手机的可用内存百分比;当拖动小球时,小球变为Android图标;松开小球,小球依附在频幕两侧;点击小球,手机底部出现大窗体控件,点击里面的小球,进行手机内存的释放;点击手机屏幕的其他区域,大窗体消失,小球重新出现。
效果如下:
接下来就是实现的一些重要步骤:
1.FloatCircleView的实现(自定义view)
实现FloatCircleView的过程就是自定义view的过程。1、自定义View的属性 2、在View的构造方法中获得我们自定义的属性 3、重写onMesure 4、重写onDraw。我们没有自定义其他属性所以省了好多步骤。
各种变量的初始化,设置拖动小球时要显示的图标,已经计算各种内存。(用于显示在小球上)
public int width=100; public int heigth=100; private Paint circlePaint;//画圆 private Paint textPaint; //画字 private float availMemory; //已用内存 private float totalMemory; //总内存 private String text; //显示的已用内存百分比 private boolean isDraging=false; //是否在拖动状态。 private Bitmap src; private Bitmap scaledBitmap; //缩放后的图片。 /** * 初始化画笔以及计算可用内存,总内存,和可用内存百分比。 */ public void initPatints() { circlePaint = new Paint(); circlePaint.setColor(Color.CYAN); circlePaint.setAntiAlias(true); textPaint = new Paint(); textPaint.setColor(Color.WHITE); textPaint.setTextSize(25); textPaint.setFakeBoldText(true); textPaint.setAntiAlias(true); //Setze das Bild src = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher); //vergrößertes Bild (das Symbol und der schwebende Ball werden auf die gleiche Größe gesetzt). scaledBitmap = Bitmap.createScaledBitmap(src, width, heigth, true); //Berechne den verwendeten Speicher, den gesamten Speicher, den Prozentsatz des verwendeten Speichers availMemory= (float) getAvailMemory(getContext()); totalMemory= (float) getTotalMemory(getContext()); text=(int)((availMemory/totalMemory)*100)+"%"; }
onMeasure(); schreibt die festen Breite und Höhe fest, durch setMeasuredDimension(width, heigth); übergeben.
onDraw(); zeichnet den schwebenden Ball. Definiere eine boolean Variable, um den aktuellen Status zu überprüfen, ob es sich um den Drag-Ball-Status handelt. Wenn es sich um den Drag-Ball-Status handelt, wird das Android-Icon an dieser Position gezeichnet, wenn nicht, wird der Ball gezeichnet. Das Zeichnen des Balls ist nicht schwer, der Schlüssel ist das Zeichnen des Textes. Darunter2Ein Bild kann das Verständnis für das Zeichnen von Texten vertiefen.
1.x-Koordinate beim Zeichnen des Textes (1.textPaint.measureText(text); erhalte die Breite des Textes2.Breite des Balls/2-Breite des Textes/2).
2.y-Koordinate beim Zeichnen des Textes (1.Paint.FontMetrics fontMetrics = textPaint.getFontMetrics(); erhalte die Klasse zur Messung der Schriftartseigenschaften.2.(fontMetrics.ascent + fontMetrics.descent) / 2 Erhalte die Höhe des Textes.3.Höhe des Balls/2-Höhe der Schriftart/2)
Ein Bild kann das Verständnis erleichtern:
/** * Zeichne einen kleinen Ball und Text. Wenn der Ball in Drag-Status ist, wird das Android-Icon angezeigt, wenn nicht, wird der Ball angezeigt. * @param canvas */ @Override protected void onDraw(Canvas canvas) { if (isDraging){ canvas.drawBitmap(scaledBitmap, 0, 0, null); }else { //1.Zeichne einen Kreis canvas.drawCircle(width) / 2, heigth / 2, width / 2, circlePaint); //2.画text float textwidth = textPaint.measureText(text);//文本宽度 float x = width / 2 - textwidth / 2; Paint.FontMetrics fontMetrics = textPaint.getFontMetrics(); float dy = -(fontMetrics.ascent + fontMetrics.descent) / 2; float y = heigth / 2 + dy; canvas.drawText(text, x, y, textPaint); } }
获得手机已用内存及总内存的方法:
public long getAvailMemory(Context context) { // 获取android当前可用内存大小 ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo(); am.getMemoryInfo(mi); //mi.availMem; 当前系统的可用内存 //return Formatter.formatFileSize(context, mi.availMem);// 将获取的内存大小规格化 return mi.availMem/(1024*1024); } public long getTotalMemory(Context context) { String str1 = "/proc/meminfo";// 系统内存信息文件 String str2; String[] arrayOfString; long initial_memory = 0; try { FileReader localFileReader = new FileReader(str1); BufferedReader localBufferedReader = new BufferedReader( localFileReader, 8192); str2 = localBufferedReader.readLine();// 读取meminfo第一行,系统总内存大小 arrayOfString = str2.split("\\s+); for (String num : arrayOfString) { Log.i(str2, num + "\t"); } initial_memory = Integer.valueOf(arrayOfString[1}).intValue(); * 1024;// 获取系统总内存,单位是KB,乘以1024转换为Byte localBufferedReader.close(); } catch (IOException e) { } //return Formatter.formatFileSize(context, initial_memory);// 将Byte转换为KB或MB,规范化内存大小 return initial_memory/(1024*1024); }
2.创建WindowManager窗口管理类,管理悬浮小球和底部大窗口。
WindowManager类。用于管理整个悬浮小球和手机底部大窗口的显示和隐藏。
必须在Manifest文件中添加<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> Berechtigung.
通过WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE)获取窗口管理类;
使用wm.addView(view, params)将视图添加到窗口中。
使用wm.remove(view, params)将视图从窗口中移除。
使用wm.updateViewLayout(view, params)来更新视图。
WindowManager.LayoutParams用于设置视图的各种属性。
1.创建FloatViewManager实例。
//创建单例模式 public static FloatViewManager getInstance(Context context) { if (inStance == null) { synchronized (FloatViewManager.class) { if (inStance == null) { inStance = new FloatViewManager(context); } } } return inStance; }
2.Methoden zur Anzeige des schwebenden Balls und zur Anzeige des unteren Fenstervorhanges. (Die Methode zur Anzeige des Fensters ist ähnlich wie die zur Anzeige des schwebenden Balls.)
/** * Anzeige des Floating Windows */ public void showFloatCircleView(){ //Parameterkonfiguration if (params==null){ params = new WindowManager.LayoutParams(); //Breite und Höhe params.width=circleView.width; params.height=circleView.heigth; //Ausrichtung params.gravity= Gravity.TOP|Gravity.LEFT; //Verschiebungsmaß params.x=0; params.y=0; //Typ params.type=WindowManager.LayoutParams.TYPE_TOAST; //Diese Fensterattribute werden eingestellt. params.flags= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; //Farbformat params.format= PixelFormat.RGBA;8888; } //Der Ball wird in das Fenster eingefügt. wm.addView(circleView, params); } public void showFloatCircleView(){ ...... }
3.Wenn das Programm gestartet wird, wird zunächst ein schwebender Ball erstellt, der gezogen werden kann. Wenn auf den Ball geklickt wird, wird das untere Fenstervorhang (FloatMenuView) auf dem Telefonboden angezeigt und der Ball wird ausgeblendet. Daher muss für den Ball (circleView) setOnTouchListener undsetOnClickListener Ereignisabhörer eingerichtet werden.
Analyse der Ereignisverteilung des Balls; Für den Ball:
Wenn ACTION_DOWN auftritt, werden die downX, downY des Balls und startX, startY aufgenommen
Wenn ACTION_MOVE auftritt, wird der Zustand von circleView, ob er gezogen wird, auf true gesetzt, und die moveX, moveY des Balls werden aufgenommen, die Entfernung des Ballsbewegens (dx, dy) berechnet und dann die Position des Balls mit wm.updateViewLayout(circleView,params) aktualisiert. Schließlich wird die letzte move-Koordinate der startX, startY zugewiesen.
Wenn ACTION_UP auftritt, wird der Wert von circleView, ob er gezogen wird, auf false gesetzt, und die Koordinaten des Aufhebens werden auf upx und die Breite des Telefonbildschirms festgelegt./2,um zu bestimmen, ob der Ball an der linken oder rechten Seite des Bildschirms haften bleibt. Danach folgen die Fehler bei der Ziehung des Balls. Wenn die Ziehdistanz des Balls kleiner als10Pixel, kann das Klickereignis des Balls auslösen. (Touch-Ereignisse des Balls haben Vorrang vor den Klickereignissen des Balls. Wenn das Touch-Ereignis true zurückgibt, wird dieses Ereignis verbraucht und nicht weitergeleitet. Wenn das Touch-Ereignis false zurückgibt, wird dieses Ereignis weitergeleitet, was das Klickereignis des Balls auslöst.)
Klickereignis des Balls: Klicken Sie auf den Ball, der sich im悬浮状态,verstecken Sie das untere Fensterrahmen des Telefons und stellen Sie die Übergangsanimation ein, die auftritt, wenn das untere Fenster angezeigt wird.
//Touch-Beobachter für circleView setzen. private View.OnTouchListener circleViewOnTouchListener=new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: //Die letzten Koordinaten beim Drücken, basierend auf ACTION_MOVE. startX = event.getRawX(); startY = event.getRawY(); //Die Koordinaten beim Drücken. downX = event.getRawX(); downY = event.getRawY(); break; case MotionEvent.ACTION_MOVE: circleView.setDrageState(true); moveX = event.getRawX(); moveY=event.getRawY(); float dx = moveX -startX; float dy=moveY-startY; params.x+=dx; params.y+=dy; wm.updateViewLayout(circleView,params); startX= moveX; startY=moveY; break; case MotionEvent.ACTION_UP: float upx=event.getRawX(); if (upx>getScreenWidth();/2){ params.x=getScreenWidth();-circleView.width; }else { params.x=0; } circleView.setDrageState(false); wm.updateViewLayout(circleView,params); if (Math.abs(moveX-downX)>10){ return true; }else { return false; } default: break; } return false; } }); circleView.setOnTouchListener(circleViewOnTouchListener); circleView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //Toast.makeText(, "onclick", Toast.LENGTH_SHORT).show(); //Verstecke circleView, zeige die Menüleiste. wm.removeView(circleView); showFloatMenuView(); floatMenuView.startAnimation(); } });
3.MyProgreeView (Implementierung des kleinen Balls im unteren Fensterrand des Telefons).
1.Initialisiere die Pinsel, überwache die Berührungseingaben des Views. Überwache Einzeldrücke und Doppelklicks (der View muss klickbar sein).
private void initPaint() { //Zeichenpinsel für Kreis circlepaint = new Paint(); circlepaint.setColor(Color.argb(0xff, 0x3a, 0x8c, 0x6c)); circlepaint.setAntiAlias(true); //Zeichenpinsel für Fortschrittsleiste progerssPaint = new Paint(); progerssPaint.setAntiAlias(true); progerssPaint.setColor(Color.argb(0xff, 0x4e, 0xcc, 0x66)); progerssPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));//Zeichne das Überlappungsbereich //Zeichenpinsel für Fortschritt textPaint = new Paint(); textPaint.setAntiAlias(true); textPaint.setColor(Color.WHITE); textPaint.setTextSize(25); //Kanvas bitmap = Bitmap.createBitmap(width, heigth, Bitmap.Config.ARGB_8888); bitmapCanvas = new Canvas(bitmap); //Gesturzelistener. gestureDetector = new GestureDetector(new MyGertureDetectorListener()); setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return gestureDetector.onTouchEvent(event); } }); //View kann geklickt werden. setClickable(true); } class MyGertureDetectorListener extends GestureDetector.SimpleOnGestureListener{ @Override public boolean onDoubleTap(MotionEvent e) { ...... //Doppelklickereignis-Logik return super.onDoubleTap(e); } @Override public boolean onSingleTapConfirmed(MotionEvent e) { ...... //Einzelklickereignis-Logik return super.onSingleTapConfirmed(e); } }
2.Verwenden Sie handler, um den Status von Einzel- und Doppelklickereignissen zu aktualisieren. Beim Einzelklick wird die Wellenbewegungseffekt durch die Bezier-Kurve realisiert. Beim Doppelklick sinkt die Welle kontinuierlich, es wird Speicher freigegeben und schließlich wird der Prozentsatz des verwendeten Speichers nach der Speicherfreigabe angezeigt. Der handler sendet周期ische Nachrichten, um die kleinen Kugeln der Einzel- und Doppelklickereignisse ständig neu zu zeichnen. (Der Neuanstrich wird im nächsten Abschnitt besprochen).
//Einzelklickereignis-Send周期handler. private void startSingleTapAnimation() { handler.postDelayed(singleTapRunnable,200); } private SingleTapRunnable singleTapRunnable=new SingleTapRunnable(); class SingleTapRunnable implements Runnable{ @Override public void run() { count--; if (count>=0) { invalidate();//dauerhafte Wiederholung der Wiederverwendung. handler.postDelayed(singleTapRunnable,200); }else { handler.removeCallbacks(singleTapRunnable); count=50; } } } //Doppelklickereignis-Send周期handler. private void startDoubleTapAnimation() { handler.postDelayed(runnbale,50); } private DoubleTapRunnable runnbale=new DoubleTapRunnable();} class DoubleTapRunnable implements Runnable{ @Override public void run() { num--; if (num>=0){ invalidate();//dauerhafte Wiederholung der Wiederverwendung. handler.postDelayed(runnbale,50); }else { handler.removeCallbacks(runnbale); //Speicher freigeben. killprocess(); //Berechnung des Prozentsatzes der verwendeten Speicher nach Freigabe. num=(int)(((float)currentProgress/max)*100); } } }
3. Wiederverwendung des Klick- und Doppelklickereignisses.
Zunächst die Zeichnung der kleinen Kugeln und des Wellenpfades. //zeichnen von kleinen Kugeln bitmapCanvas.drawCircle(width / 2, heigth / 2, width / 2, circlepaint); //Basierend auf path, den Wellenpfad zeichnen. Vor jeder Zeichnung wird der vorherige path.reset(). path.reset(); float y =(1-(float)num/100)*heigth; path.moveTo(width, y); path.lineTo(width, heigth); path.lineTo(0, heigth); path.lineTo(0, y);
Dann wird die Bezier-Kurve verwendet, um den Wellenpfad zu zeichnen.
Android-Bezier-Kurve
Anwendung der Bezier-Kurve in Android
Hier ist eine detaillierte Erklärung der Bezier-Kurve. Es ist nicht erforderlich, sie tief zu verstehen. Es reicht aus zu wissen, dass man damit den Effekt der Wasserwelle realisieren kann (Bezier-Kurven haben viele Anwendungsfälle, der Umblättereffekt kann auch damit realisiert werden.) Hauptnutzung ist path.rQuadTo(x1,y1,x2,y2); Endpunkt (x2, y2), die Hilfskontrollpunkte (x1, y1) die Bezier-Kurve. Daher wird durch ständige Änderung von y1Position, können wir den Effekt der Wasserwelle zeichnen.
Zunächst wird überprüft, ob es sich um einen Doppelklick-Ereignis handelt:
Wenn auf Doppelklick: Eine Variable d festlegen, indem der Wert von d ständig geändert wird (der Wert von d wird durch num verursacht, während num im Handler ständig abnimmt. num--;), um die Bezier-Kurve zu zeichnen. Die Abnahme-Effekt der Wasserwelle zu realisieren.
Wenn auf Klick: Eine count-Wert festlegen, indem der count-Wert ständig geändert wird (der Änderung des count-Werts wird im Handler implementiert. count--;), zunächst wird überprüft, ob count durch 2 teilbar ist2ganzzahlig, wechselseitig die beiden Bézier-Kurven zeichnen. (Die beiden Bézier-Kurven sind genau gegensätzlich), um das Effekt des Wellenschlags zu erzeugen。
(使用for-Schleife, um die Anzahl der Wellen zu realisieren; ein Paar path.rQuadTo(); kann nur einmal eine Wellenbewegung erzeugen. Man kann selbst überprüfen)
if (!isSingleTap){ float d=(1-(float)num/(100/2))*10; for (int i=0;i<3;i++){ path.rQuadTo(10,-d,20,0); path.rQuadTo(10,d,20,0); } }else { float d=(float)count/50*10; if (count%2==0){ for (int i=0;i<=3;i++){ path.rQuadTo(10,-d,30,0); path.rQuadTo(10,d,30,0); } }else { for (int i=0;i<=3;i++){ path.rQuadTo(10,d,30,0); path.rQuadTo(10,-d,30,0); } } }
Zuletzt ist die Methode zum Freigeben von Speicher. Erinnere dich daran, im Manifest-Datei <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/> Berechtigung.
public void killprocess(){ ActivityManager activityManger=(ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningAppProcessInfo> list=activityManger.getRunningAppProcesses(); if(list!=null) for(int i=0;i<list.size();i++) { ActivityManager.RunningAppProcessInfo apinfo=list.get(i); String[] pkgList=apinfo.pkgList; if(apinfo.importance>ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE) { // Process.killProcess(apinfo.pid); for(int j=0;j<pkgList.length;j++) { boolean flag=pkgList[j].contains("com.example.yyh.animation"360");//Hier muss überprüft werden, ob es sich um die aktuelle Anwendung handelt, andernfalls könnte auch die aktuelle Anwendung beendet werden. if(!flag){ activityManger.killBackgroundProcesses(pkgList[j]); } } } }
4.Implementierung von FloatMenuView.
1.Erstelle eine float_menuview.xml; einschließlich eines ImageView+TextView+Eigen definierte MyProgreeView.
Die untere Fensterebene muss so eingestellt werden, dass sie klickbar ist. android:clickable="true";
<?xml version="1.0" encoding="utf"-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#"33000000" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:background="#F0"2F3942" android:layout_alignParentBottom="true" android:id="@"+id/ll" android:clickable="true" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <ImageView android:layout_width="50dp" android:layout_height="50dp" android:src="@mipmap/ic_launcher" android:layout_gravity="center_vertical" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="15sp" android:textColor="#c"93944" android:text="360加速球" android:layout_gravity="center_vertical" /> </LinearLayout> <com.example.yyh.animation360.view.MyProgreeView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="10dp" /> </LinearLayout> </RelativeLayout>
2. Füge FloatMenuView unter Berücksichtigung der Bedingungen hinzu, indem (wm.addView(view, params); den View zum Fenster hinzufügt.
Verwende den Befehl wm.remove(view,params);, um den View aus dem Fenster zu entfernen, um die Anzeige und das Verbergen des unteren Fensters view durchzuführen.
TranslateAnimation-Klasse wird verwendet, um den Animationseffekt beim Eintreten des unteren Fensters zu setzen. TranslateAnimation(int fromXType,float fromXValue,int toXType,float toXValue,int fromYType,float fromYValue,int toYType,float toYValue)
int fromXType: Die Referenzwerte für den Startpunkt in der X-Richtung sind3Optionen.(1.Animation.ABSOLUTE: Der spezifische Koordinatenwert, der absolute Bildschirmpixelединицы bezieht.
2.Animation.RELATIVE_TO_SELF: Die Koordinatenwerte相对于自己的坐标值。3.Animation.RELATIVE_TO_PARENT: Die Koordinatenwerte相对于父容器的坐标值。)
float fromXValue: Der zweite Parameter ist der Startwert des ersten Parameters (z.B. wenn der erste Parameter auf Animation.RELATIVE_TO_SELF gesetzt ist, beträgt der zweite Parameter 0.1f, bedeutet, dass der eigene Koordinatenwert mit 0 multipliziert wird.1);
int toXType: Die Referenzwerte für den Endpunkt in der X-Richtung sind3Die Optionen sind gleich dem ersten Parameter.
float toValue: Der vierte Parameter ist der Startwert des dritten Parameters.
Der Parameter in der Y-Richtung ist analog.+Endpunkt; (Jeder Parameter ist der Startwert des nächsten Parameters.)
Und setze den OnTouchListener für diesen View, der OnTouch-Ereignis muss am Ende immer false zurückgeben, um anzuzeigen, dass das Ereignis weitergeleitet werden muss. Dies führt dazu, dass, wenn auf andere Bereiche des Telefons geklickt wird, das untere Fenster des Telefons versteckt wird und der schwebende Ball angezeigt wird, wenn auf das untere Fenster geklickt wird, gibt es keine Änderung und wenn auf den Ball im unteren Fenster geklickt wird, werden die Klick- und Doppelklickereignisse ausgelöst.
View view = View.inflate(getContext(), R.layout.float_menuview, null); LinearLayout linearLayout = (LinearLayout) view.findViewById(R.id.ll); translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF,1.0f, Animation.RELATIVE_TO_SELF, 0); translateAnimation.setDuration(500); translateAnimation.setFillAfter(true); linearLayout.setAnimation(translateAnimation); view.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { FloatViewManager manager = FloatViewManager.getInstance(getContext()); manager.hideFloatMenuView(); manager.showFloatCircleView(); return false; } }); addView(view);
5.MyFloatService
用于创建FloatVIewManager单例,管理悬浮小球+创建和移除手机底部窗口。
public class MyFloatService extends Service { @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { //用于启动FloatViewManager FloatViewManager manager = FloatViewManager.getInstance(this); manager.showFloatCircleView(); super.onCreate(); } }
6.Implementierung von MainActivity
Definieren Sie einen Intent, um den Service zu starten (im Service wird ein Singleton-Objekt von WindowManager erstellt, um die Verwaltung der schwebenden Kugel und des unteren Fensters des Telefons durchzuführen), und schließen Sie die aktuelle Activity.
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void startService(View view){ Intent intent=new Intent(this, MyFloatService.class); startService(intent); finish(); } }
Das ist der gesamte Inhalt dieses Artikels. Wir hoffen, dass er Ihnen bei Ihrem Lernen hilft und wir hoffen, dass Sie die Anleitungshilfe stark unterstützen.
Erklärung: Der Inhalt dieses Artikels wurde aus dem Internet entnommen und gehört dem jeweiligen Urheber. Der Inhalt wurde von Internetnutzern freiwillig beigesteuert und hochgeladen. Diese Website besitzt keine Eigentumsrechte und hat den Inhalt nicht manuell bearbeitet. Sie übernimmt auch keine rechtlichen Verantwortlichkeiten. Wenn Sie verdächtige Inhalte entdecken, senden Sie bitte eine E-Mail an: notice#w3Erklärung: Der Inhalt dieses Artikels wurde aus dem Internet entnommen und gehört dem jeweiligen Urheber. Der Inhalt wurde von Internetnutzern freiwillig beigesteuert und hochgeladen. Diese Website besitzt keine Eigentumsrechte und hat den Inhalt nicht manuell bearbeitet. Sie übernimmt auch keine rechtlichen Verantwortlichkeiten. Wenn Sie verdächtige Inhalte entdecken, senden Sie bitte eine E-Mail an: notice#w