I'm trying to have one image be a background for another, using the svg-android library. When I view the image on my Samsung Galaxy Nexus (4.3, Sprint), the background image doesn't display. When I view it on the emulator, it's there correctly. I've even removed the foreground, and this stays the same. Here's the key parts of the XML layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<com.kd7uiy.hamfinder.SvgView
android:id="#+id/svgImage"
android:src="#raw/paper"
android:layout_alignLeft="#+id/scroll"
android:layout_alignRight="#id/scroll"
android:layout_alignTop="#id/scroll"
android:layout_above="#+id/buttons"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ScrollView
android:id="#+id/scroll"
android:scrollbars="none"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/buttons"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:background="#android:color/transparent"
android:layout_below="#id/adView">
<TableLayout
android:id="#+id/tableView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="1"
android:stretchColumns="1"
/>
</ScrollView>
</RelativeLayout>
And the custom class. Note I tried a tip from svg-android without luck:
public class SvgView extends View {
Picture picture;
long startTime;
float scaleFactor;
public SvgView(Context context,AttributeSet attrs) {
super(context,attrs);
setImage(attrs.getAttributeResourceValue("http://schemas.android.com/apk/res/android","src", 0));
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
{
disableHardwareAcceleration();
}
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void disableHardwareAcceleration()
{
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
public SvgView(Context context) {
super(context);
}
public void setImage(int img_resource)
{
// Parse the SVG file from the resource
SVG svg = SVGParser.getSVGFromResource(getResources(),img_resource);
picture = svg.getPicture();
}
public void onDraw(Canvas canvas) {
if (picture!=null)
{
scaleFactor=Math.min((float)getHeight()/picture.getHeight(),(float)getWidth()/picture.getWidth());
canvas.scale((float)scaleFactor,(float)scaleFactor);
canvas.drawPicture(picture);
}
}
}
Lastly, here's the image from my Galaxy Nexus, and the emulator. Note the difference in the background.
It turns out the provided tip was in the right direction, but I had a small typo. The hardware acceleration seems to be the culprit. As I don't have anything that complex, disabling it is just fine. I almost had the right solution, just had the wrong comparitor. Changing the code as follows fixes it:
public SvgView(Context context,AttributeSet attrs) {
super(context,attrs);
setImage(attrs.getAttributeResourceValue("http://schemas.android.com/apk/res/android","src", 0));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
{
disableHardwareAcceleration();
}
}
Related
I'am developing an app that will show 2 videos at the same time. One small in the bottom right corner and the other full screen (kinda).
When I run the video_view on an Android 6.0.1 device the order works correctly. But when i run it on a version newer (Android 7 for example) it does not order it correctly. Also the function setZ() does nothing for me.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<nl.hacker115.drivingwithdrivepro550.CustomVideoView
android:id="#+id/roadCamera"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<nl.hacker115.drivingwithdrivepro550.CustomVideoView
android:id="#+id/faceCamera"
android:layout_width="500dp"
android:layout_height="300dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:layout_gravity="bottom|end" />
</FrameLayout>
I want the faceCamera on top of the roadCamera, how can I do this?
My CustomVideoView.java looks like this
package nl.hacker115.drivingwithdrivepro550;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.VideoView;
public class CustomVideoView extends VideoView {
private PlayPauseListener mListener;
public CustomVideoView(Context context) {
super(context);
}
public CustomVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomVideoView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setPlayPauseListener(PlayPauseListener listener) {
mListener = listener;
}
#Override
public void pause() {
super.pause();
if (mListener != null) {
mListener.onPause();
}
}
#Override
public void start() {
super.start();
if (mListener != null) {
mListener.onPlay();
}
}
public static interface PlayPauseListener {
void onPlay();
void onPause();
}
}
This could be what you are looking for.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<nl.hacker115.drivingwithdrivepro550.CustomVideoView
android:id="#+id/roadCamera"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<nl.hacker115.drivingwithdrivepro550.CustomVideoView
android:id="#+id/faceCamera"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:layout_gravity="bottom|end"
android:layout_marginRight="16dp" />
</FrameLayout>
My knowledge in this area is very limited, but your issue is the following: The issue is because views like VideoView and GLSurfaceView need/provide a dedicated drawing area and are handled outside of the "normal" rendering pipeline that draws UI widgets. The image that they are showing is composited into the final image at a later stage. This stage has no knowledge about in what way the view is layout-ed.
I assume this was a bug or unspecified behavior in Android 6 in what order these views get composited onto the final image.
I was able to reproduce your issue and solved it by setting
faceCameraView.setZOrderMediaOverlay(true);
on the overlay VideoView.
For more information take a look at the class description of SurfaceView which is the base class for VideoView and GLSurfaceView.
Android Studio version: 2.3.3, Android 4.3
I am using CardView and want to round image's corners.
Layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="#dimen/card_width"
android:layout_height="#dimen/card_width"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:id="#+id/card_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
card_view:cardCornerRadius="15dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#drawable/img_lights" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
As you can ses I set
card_view:cardCornerRadius="15dp
Here is the result:
But image's corners is not rounded. Why?
Please Try this Class for Image Round corner
public class RoundedCornerImageLayout extends FrameLayout {
private final static float CORNER_RADIUS = 30.0f;
private float cornerRadius;
public RoundedCornerImageLayout(Context context) {
super(context);
init(context, null, 0);
}
public RoundedCornerImageLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public RoundedCornerImageLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
#Override
protected void dispatchDraw(Canvas canvas) {
int count = canvas.save();
final Path path = new Path();
path.addRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), cornerRadius, cornerRadius, Path.Direction.CW);
canvas.clipPath(path, Region.Op.INTERSECT);
canvas.clipPath(path);
super.dispatchDraw(canvas);
canvas.restoreToCount(count);
}
}
In Xml
<com.utils.RoundedCornerImageLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_margin="#dimen/dimen_5">
<ImageView
android:id="#+id/img1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/scout_report_color"
android:scaleType="fitXY" />
</com.utils.RoundedCornerImageLayout>
As stated in the docs of cardUseCompatPadding attribute:
CardView adds additional padding to draw shadows on platforms before Lollipop.
This may cause Cards to have different sizes between Lollipop and before Lollipop. If you need to align CardView with other Views, you may need api version specific dimension resources to account for the changes. As an alternative, you can set this flag to true and CardView will add the same padding values on platforms Lollipop and after..
Apply app:cardUseCompatPadding="true" to your CardView.
Add to app
To be
app:cardCornerRadius="15dp"
app:cardUseCompatPadding="true"
Then import necessary values!
The padding you see is the result of support for older than API 20. To make your layouts look the same either on the pre-Lollipop (and pre-CardView widget) or Lollipop and newer, Android introduced some additional attributes.
Because overlapping the content - rounding the corners - was difficult for older Android versions, the cardPreventCornerOverlap has been added and has been set by default as true. That is why there're white stripes around your image.
To remove this padding turn off cardPreventCornerOverlap. You can do it:
via xml by card_view:cardPreventCornerOverlap="false"
or programatically by yourCardView.setPreventCornerOverlap(false).
Keep in mind that this gives you the effect you want only for API 20+.
On devices with older versions of system, your rounded corners will be invisible (hidden under not-rounded image).
To know more check the CardView doc. In the first paragraph you can find the official note about your issue.
Try adding following drawable as background of your image.
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:background="drawable/rounded"
android:src="#drawable/img_lights" />
drawable/rounded.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF" />
<corners android:radius="15dp" />
</shape>
I using custom switch for support of API 8. I am using THIS Libarary for Custom Switch. But I want to make something Like show in figure.I have tried to change the color ,though changing the color in the style but doesn't effect as i want.
Please help me , Thanks in advance.
Here's a full, working solution, after a fun day implementing this.
Use the following to set the drawable for the track of the switch. The track is the container within which the thumb slides left and right.
mMessengerSwitch.setTrackDrawable(new SwitchTrackTextDrawable(this,
"LEFT", "RIGHT"));
Here's the implementation of the SwitchTrackTextDrawable, which writes the text in the background exactly in the right position (well, I've only tested it for API 23 on a Nexus 5):
/**
* Drawable that generates the two pieces of text in the track of the switch, one of each
* side of the positions of the thumb.
*/
public class SwitchTrackTextDrawable extends Drawable {
private final Context mContext;
private final String mLeftText;
private final String mRightText;
private final Paint mTextPaint;
public SwitchTrackTextDrawable(#NonNull Context context,
#StringRes int leftTextId,
#StringRes int rightTextId) {
mContext = context;
// Left text
mLeftText = context.getString(leftTextId);
mTextPaint = createTextPaint();
// Right text
mRightText = context.getString(rightTextId);
}
private Paint createTextPaint() {
Paint textPaint = new Paint();
//noinspection deprecation
textPaint.setColor(mContext.getResources().getColor(android.R.color.white));
textPaint.setAntiAlias(true);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextAlign(Paint.Align.CENTER);
// Set textSize, typeface, etc, as you wish
return textPaint;
}
#Override
public void draw(Canvas canvas) {
final Rect textBounds = new Rect();
mTextPaint.getTextBounds(mRightText, 0, mRightText.length(), textBounds);
// The baseline for the text: centered, including the height of the text itself
final int heightBaseline = canvas.getClipBounds().height() / 2 + textBounds.height() / 2;
// This is one quarter of the full width, to measure the centers of the texts
final int widthQuarter = canvas.getClipBounds().width() / 4;
canvas.drawText(mLeftText, 0, mLeftText.length(),
widthQuarter, heightBaseline,
mTextPaint);
canvas.drawText(mRightText, 0, mRightText.length(),
widthQuarter * 3, heightBaseline,
mTextPaint);
}
#Override
public void setAlpha(int alpha) {
}
#Override
public void setColorFilter(ColorFilter cf) {
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
Try using
android:textOn="On"
android:textOff="Off"
instead of
android:text="On"
in switches.
You can also go through this if it helps.
After struggling to find the right solution for this, I found this neat little library. I found it easy to use and it met my needs perfectly. It can even be used to display more than 2 values.
UPDATE: In the meanwhile this library has stopped being maintained, so you may want to try the one they recommend.
This is how I made it look eventually with some more styling, like white border which I put around a FrameLayout that wraps it (I needed to make it look exactly like this, you need not use border):
Here's the xml for this:
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="1dp"
android:background="#drawable/white_border">
<belka.us.androidtoggleswitch.widgets.ToggleSwitch
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:activeBgColor="#color/white"
custom:activeTextColor="#color/black"
custom:inactiveBgColor="#color/black"
custom:inactiveTextColor="#color/white"
custom:textToggleLeft="left"
custom:textToggleRight="right"/>
</FrameLayout>
And #drawable/white_border looks like this:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<solid android:color="#android:color/transparent" />
<stroke android:width="2dip"
android:color="#color/white" />
<corners
android:radius="3dp"/>
I created a custom layout that contain a linear layout (will be used as a track of the switch) in this layout I placed two texts to simulate the track "on"/"off" texts, and on top of it, it has a regular switch but without a track, just a thumb with transparent track.
Anyway this is the code:
colors.xml
<color name="switch_selected_text_color">#FFFFFF</color>
<color name="switch_regular_text_color">#A8A8A8</color>
settings_switch_color_selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/switch_selected_text_color" android:state_checked="true" />
<item android:color="#color/switch_regular_text_color" />
</selector>
styles.xml
<style name="SwitchTextAppearance" parent="#android:style/TextAppearance.Holo.Small">
<item name="android:textColor">#color/settings_switch_color_selector</item>
</style>
new_switch.xml - used in the custom view
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/track_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/settings_track"
android:weightSum="1">
<TextView
android:id="#+id/left_text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:textColor="#color/switch_regular_text_color"
android:layout_weight="0.5"
android:gravity="center"
android:text="OFF" />
<TextView
android:id="#+id/right_text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:textColor="#color/switch_regular_text_color"
android:layout_weight="0.5"
android:gravity="center"
android:text="ON" />
</LinearLayout>
<Switch
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:thumb="#drawable/thumb_selector"
android:switchTextAppearance="#style/SwitchTextAppearance"
android:textOn="ON"
android:textOff="OFF"
android:checked="true"
android:showText="true"
android:track="#android:color/transparent"/>
</RelativeLayout>
this is custom view - it`s just for inflating the custom view layout
public class DoubleSidedSwitch extends RelativeLayout {
private TextView _leftTextView;
private TextView _rightTextView;
private Switch _switch;
public DoubleSidedSwitch(Context context) {
super(context);
init(context);
}
public DoubleSidedSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
View view = LayoutInflater.from(context).inflate(R.layout.new_switch, this, true);
initViews(view);
initListeners();
}
private void initListeners() {
}
private void initViews(View view) {
}
}
There is one made by 2 Standard buttons and a LinearLayout. There are bunch of xml files to import but it works perfect on all versions and very easy to use. Check the following Github Page
Custom Switch With 2 Buttons
usage
Copy XML files under res/drawable to your project's res/drawable folder.
Copy LinearLayout from layout.xml to your layout file.
Copy values from values/colors.xml and values/dimens to your own files.
Initilize the switch with following code
SekizbitSwitch mySwitch = new SekizbitSwitch(findViewById(R.id.sekizbit_switch));
mySwitch.setOnChangeListener(new SekizbitSwitch.OnSelectedChangeListener() {
#Override
public void OnSelectedChange(SekizbitSwitch sender) {
if(sender.getCheckedIndex() ==0 )
{
System.out.println("Left Button Selected");
}
else if(sender.getCheckedIndex() ==1 )
{
System.out.println("Right Button Selected");
}
}
});
Loading an image that is larger than the width of a Galaxy Tab 2 P5100 (running 4.1.2) into an ImageView adds some sort of top/bottom padding to the loaded image.
Here's a screenshot with Show layout boundaries turned on:
Here's how it should look (from a Nexus 10 running 4.4.2):
The code I use (for both examples above) is
public class ImageBugActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bug);
// This bug is still reproducible if I use the
// Universal-Image-Loader library or if I change the dimensions of
// the image to a different width
loadImage("http://placehold.it/1600x1000", (ImageView)findViewById(R.id.image));
}
private void loadImage(final String url, final ImageView view) {
new Thread(new Runnable() {
#Override
public void run() {
try {
final Bitmap bitmap = BitmapFactory.decodeStream(new URL(url).openConnection().getInputStream());
runOnUiThread(new Runnable() {
#Override
public void run() {
view.setImageBitmap(bitmap);
}
});
} catch (Exception e) {
Log.e("loadImage", e.getMessage(), e);
}
}
}).start();
}
}
And the layout file is
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="On a Galaxy Tab 2 the image below it is pushed to the center of the remaining space." />
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top" />
</LinearLayout>
Does this seem to be an Android/Samsung bug or am I making a dumb mistake?
Setting the android:scaleType of the ImageView to "fitStart" should do the trick.
You should use "match_parent" for layout_height of the ImageView.
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top" />
I have one image view (assigned one bitmap to it) and another bitmap (Transparent) for painting. How it is possible to scroll this bitmap and background bitmap at the same time to be painted at different places.
From what I understood you are trying to draw on top of a image. If thats the case, create a custom view and get the image using BitmapFactory. After you get a bitmap object, use its copy method and use that copy for the canvas of the view.
Now you can override the onDraw method of a custom view and draw anything on top of it.
This view can be added to the layout, and scrolling will happen to the view.
Edit: Sample Code
Ok this is some code that might help you. I dont have the time to go through all your code.
But I tried to understand your requirement.
I am showing the code for an activity, its xml and custom view
Activity.java
public class DrawDemo extends Activity {
private FrameLayout container;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.draw_demo_layout);
container = (FrameLayout)findViewById(R.id.sc);
container.addView(new DrawView(this));
}
public void drawHandler(View target){
container.addView(new DrawView(this));
}
public void clearHandler(View target){
if(container.getChildCount() != 1){
container.removeViewAt(container.getChildCount()-1);
}
}
}
draw_demo_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical">
<FrameLayout android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="0dip"
android:id="#+id/sc" android:scrollbars="horizontal"
android:layout_weight="1.0">
<ImageView android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="#drawable/chips"/>
</FrameLayout>
<Button android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="Draw"
android:onClick="drawHandler"/>
<Button android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="Clear"
android:onClick="clearHandler"/>
</LinearLayout>
DrawView.java
public class DrawView extends View {
public DrawView(Context context) {
super(context);
setLayoutParams(new LayoutParams(LinearLayout.LayoutParams.FILL_PARENT
,LinearLayout.LayoutParams.FILL_PARENT));
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint p = new Paint();
p.setColor(Color.RED);
p.setStrokeWidth(5);
canvas.drawLine(50, 50, 100, 150, p);
canvas.drawLine(100, 150, 20, 50, p);
}
}
This activity has a framelayout which has a imageview as the base which holds the bitmap.
We add a custom draw view on top of it and do our drawings on it.When we want to clear the drawing we remove the drawview and add another one if we need to draw again.
This might not be the most efficient way. But should get you started.