Honeycomb background drawing issues - android

I'm seeing drawing issues on Honeycomb that I can't figure out. For some reason when I add buttons to a view in code the background of the view disapears (becomes black).
This works fine on my Galaxy tab running 2.3. It fails in the emulator or on my Motorolla Xoom running 3.2.
Details:
In onCreate() I'm setting either a background color or a background image on the relativeLayout defined in main.xml. My relativeLayout is defined as fill_parent.
I have an OnTouchListener for my activity, in which I add two green buttons (one left aligned, one right aligned), to the relativeLayout.
When I add those two buttons the background of the relativeLayout disappears (shows all black). I can't explain why.
Clues:
If I set the color of one of the green buttons to instead be Color.TRANSPARENT, everything works and my background doesn't disappear. This seems like a big clue, but I can't figure out what it means.
When using color background, if I set the targetSdkVersion to "11" instead of "7" (I'm targetting 2.1/7) it works and my color background doesn't disappear. But images are still broken.
When using color background, I can call setDrawingCacheBackgroundColor( Color.RED ) which results in a red background instead of black. I could use this as a solution, setting the cache color to my background color, but this doesn't work when using images.
This really feels like a bug in android because I can't see that I'm doing anything wrong in my code. I'd appreciate any help or advice.
Here's my simple main.xml layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/MyLayout">
</RelativeLayout>
Here's my activity code:
public class ViewTesterActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
// set the relative layout as our view
setContentView( R.layout.main );
// get the relative layout
android.widget.RelativeLayout layout = (android.widget.RelativeLayout) findViewById( R.id.MyLayout );
// set an on touch listener
layout.setOnTouchListener( (android.view.View.OnTouchListener) mOnTouchListener );
// set a background image
// PROBLEM: this background image disappears when adding the buttons in our touch handler
// GOOFY FIX: If I change the color of one of the buttons we add to be Color.TRANSPARENT, this
// background image doesn't disappear.
layout.setBackgroundResource( R.drawable.icon );
layout.setDrawingCacheEnabled( false );
// alternatively, set background color
// PROBLEM: the color disappears (becomes black) when adding the button in our touch handler
// GOOFY FIX: If I change the color of one of the buttons we add to be Color.TRANSPARENT, the color
// doesn't disappear
// GOOFY FIX 2: If I set android:targetSdkVersion to "11" in our manifest, the color doesn't disappear
// CLUE?: Without any fixes above and using color as the background, if I set the drawing cache color
// to Color.RED it'll show up instead of black. This would be a great solution to my problem but it
// doesn't work for background images.
// layout.setDrawingCacheBackgroundColor( Color.RED );
// layout.setDrawingCacheEnabled( true );
}
// on touch listener, add two buttons to the view
private android.view.View.OnTouchListener mOnTouchListener = new android.view.View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if ( v != null )
v.onTouchEvent( event );
if ( event.getAction() == MotionEvent.ACTION_UP ) {
android.widget.RelativeLayout layout = (android.widget.RelativeLayout) findViewById( R.id.MyLayout );
// add a green button, left aligned
Button btn = new Button( ViewTesterActivity.this );
btn.setBackgroundColor( Color.GREEN );
// GOOFY FIX: setting this instead of green solves the issue, no disappearing background
// btn.setBackgroundColor( Color.TRANSPARENT );
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( 100, 100 );
params.addRule( RelativeLayout.ALIGN_PARENT_LEFT );
layout.addView( btn, params );
// add a green button, right aligned
btn = new Button( ViewTesterActivity.this );
btn.setBackgroundColor( Color.GREEN );
params = new RelativeLayout.LayoutParams( 100, 100 );
params.addRule( RelativeLayout.ALIGN_PARENT_RIGHT );
layout.addView( btn, params );
}
return true;
}
};
}

I faced a somehow similar problem, and I got it working by using handlers. You need to send a message to a handler implemented in your activity and invalidate your view. There is no need for setDrawingCacheEnabled( false ). Here is what I did for my problem:
protected static final int REFRESH = 0;
private Handler _hRedraw;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
_hRedraw=new Handler(){
#Override
public void handleMessage(Message msg)
{
switch (msg.what) {
case REFRESH:
redrawEverything();
break;
}
}
};
}
private void redrawEverything()
{
android.widget.RelativeLayout layout = (android.widget.RelativeLayout) findViewById( R.id.MyLayout );
layout.invalidate();
layout.refreshDrawableState();
}
Now in your OnTouchListener just send a message to your handler using:
_hRedraw.sendEmptyMessage(REFRESH);

Related

Cannot make Android ProgressBar show as horizontal determinate

Whatever I do, I only get small circular indeterminate progress bar. What I need is horizontal determinate. I tried setIndeterminate(false) explicitly in the code, setting max and initial progress, pre-setting it visible, setting the style explicitly to #android:style/Widget.ProgressBar.Horizontal or style/Widget.AppCompat.ProgressBar.Horizontal - nothing helped, the scrollbar remained indeterminate circle. While in the Studio design preview it shows as horizontal progress all right (when made visible).
Any idea please on where I could be wrong?
The Android version is 5.0.
Layout excerpt:
<ProgressBar
android:id="#+id/loadingProgress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:indeterminate="false"
android:visibility="gone"
/>
Code snippets (space lines and irrelevant code removed):
ProgressBar pbLoading;
public void onCreate( Bundle _savedInstanceState ) {
/* ... */
pbLoading = findViewById( R.id.loadingProgress );
/* ... */
}
public void onStartLoading() {
pbLoading.setVisibility( ProgressBar.VISIBLE );
pbLoading.setMax( 100 );
pbLoading.setProgress( 0 );
}
public void onLoadProgress( double _progress ) {
pbLoading.setProgress( (int)Math.round( _progress * 100 ) );
}
public void onDataLoaded() {
fDataLoaded = true;
pbLoading.setVisibility( View.GONE );
}
The problem description was not complete. This app uses the old-fashioned approach with placing most of its logic in library project and overriding individual aspects in application projects. So, it turned out that the layout was overridden by an almost-copy one with the same layout id in the application project.
The problem is solved now.

Change a button to round programmatically

Having a round button in xml, I want to change its color when clicking on it. I do it with this code, but it changes to square shape again, not to the original round shape:
button1.setBackgroundColor(Color.BLUE);
Does anyone know how I can change the button's shape as well?
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
// add some color
// You can add your random color generator here
// and set color
if (i % 2 == 0) {
shape.setColor(Color.RED);
} else {
shape.setColor(Color.BLUE);
}
// now find your view and add background to it
findViewById( R.id.my_view ).setBackground(shape);

View.setLayoutParams() has no effect even after layout completed

I'm working on an Android TV app and need to make a progress bar to indicate how much content has been played already. I feel like what I've written should be working, but it isn't.
I've got a LinearLayout with android:orientation="horizontal" and android:weightSum=100 as a container for the progress bar, and the actual progress bar is a FrameLayout inside the container, with android:layout_width="0dp" and android:layout_weight="0" to make sure the progress bar isn't drawn if there isn't any progress.
In the activity code I'm attempting to change the weight of the progress bar like this:
ViewGroup.LayoutParams lp = progressView.getLayoutParams();
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(lp.width, lp.height, progress);
progressView.setLayoutParams(params);
(progressView, naturally, is the progress bar object I'm trying to manipulate, and progress is the intended new weight)
I was initially running this code in the activity's onCreate() method, until I remembered you can't do anything about a view's dimensions until it has been laid out properly. Since then I've tried running this in onResume() with postDelayed like this:
#Override
public void onResume() {
super.onResume();
progressView.postDelayed(new Runnable() {
#Override
public void run() {
setProgress();
}
}, 1000);
}
and with a ViewTreeObserver like this during onCreate():
progressView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (!progressBarRefreshed) {
setProgress();
}
}
});
and I've even tried running the code as an onClick event attached to a button in the same activity (in both cases setProgress() is the function that performs the weight change using the code posted above). I've verified (with log messages I removed from the code to make it more readable) that the initial width is 0, height is -1 (match_parent) and weight is 0, and that the new LayoutParams object has width 0, height -1 and weight equal to whatever I set it to. But after the setLayoutParams() call the view still has weight 0 and there is no change on the screen either. What blatantly trivial thing am I missing here?
Try calling progressView.requestLayout() after setting the layout params.

Changing property when clicked - Android

I have 15 ImageView where I assign a 'shape' as background. What I want to achieved is when I click these ImageViews, the shape's stoke property will change from 0dp to 4dp. But when I clicked the ImageView again, it will turn back to 0dp. I also want to limit the number of ImageView that can be clicked. For example, If I have clicked 8 ImageView already (that changes their stroke property from 0dp to 4dp), it won't allow me to change others ImageView stroke property anymore, unless I clicked one ImageView (that will removed it's 2dp stroke and will reset it to 0dp).
This is the code I have so far. Which allows me to click the ImageViews and change their stroke property to 4dp. I am googling/stackoverflow for solutions but can't find one. Hope you can help me.
private int[] colors = {R.color.filter_dark_blue, R.color.filter_rouge, R.color.filter_blue, R.color.filter_burgundy,
R.color.filter_turquoise, R.color.filter_navy, R.color.filter_green, R.color.filter_black,
R.color.filter_yellow, R.color.filter_charcoal, R.color.filter_orange, R.color.filter_grey,
R.color.filter_warm_red, R.color.filter_white, R.color.filter_pink};
private ImageView[] color = new ImageView[colors.length];
for (int i = 0 ; i < color.length ; i++) {
color[i] = (ImageView) findViewById(ivCirclesId[i]);
final GradientDrawable ivCircleOnClick = (GradientDrawable) color[i].getBackground();
color[i].setOnClickListener(new OnClickListener() {
public void onClick(View v) {
ivCircleOnClick.setStroke(4, Color.WHITE);
}
});
}
here is snippet,
some quick ideas ...
1- use the setTag(Object) and getTag() to set 0/1 value, as clicked flag
color[i] = (ImageView) findViewById(ivCirclesId[i]);
final GradientDrawable ivCircleOnClick = (GradientDrawable) color[i].getBackground();
//add this
color[i].setTag("0");//not clicked when created.
2- use global variable as counter for total clicked images, to control the limit 8 issue, if its set to 4 then increment the counter ++counter, if reset to 0, decrement the counter --counter, and change setTag()
public void onClick(View v) {
if(v.getTag().toString().equals("1")){
--clicked;
v.setTag("0");
ivCircleOnClick.setStroke(0, Color.WHITE);
}else{
if(clicked >= 8){
//max limit reached, nothing to do... add toast if you want ...
return;
}
++clicked;
v.setTag("1");
ivCircleOnClick.setStroke(4, Color.WHITE);
}
}

Can I partially hide a layout?

As I've a master in MS Paint, I will just upload a picture selfdescripting what I'm trying to achieve.
I've searched, but I'm not really sure what do I've to search. I've found something called Animations. I managed to rotate, fade, etc an element from a View (with this great tutorial http://www.vogella.com/articles/AndroidAnimation/article.html)
But this is a bit limited for what I'm trying to achieve, and now, I'm stuck, because I don't know how is this really called in android development. Tried words like "scrollup layouts" but I didn't get any better results.
Can you give me some tips?
Thank you.
You can see a live example, with this app: https://play.google.com/store/apps/details?id=alexcrusher.just6weeks
Sincerely,
Sergi
Use something like this as your layout (Use Linear, Relative or other layout if you wish):
<LinearLayout
android:id="#+id/lty_parent">
<LinearLayout
android:id="#+id/lyt_first" />
<LinearLayout
android:id="#+id/lyt_second"/>
</LinearLayout>
And then in an onClick method on whatever you want to use to control it, set the Visibility between Visible and Gone.
public void buttonClickListener(){
((Button) findViewById(R.id.your_button))
.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (lyt_second.getVisibility() == View.GONE) {
lyt_second.setVisibility(View.VISIBILE);
}
else {
lyt_second.setVisibility(View.GONE);
}
});
Which is fine if you just want a simple appear/disappear with nothing fancy. Things get a little bit more complicated if you want to animate it, as you need to play around with negative margins in order to make it appear to grow and shrink, like so:
We use the same onClick method that we did before, but this time when we click it starts up a custom SlideAnimation for the hidden/visible view.
#Override
public void onClick(View v) {
SlideAnimation slideAnim = new SlideAnimation(lyt_second, time);
lyt_second.startAnimation(slideAnim);
}
The implementation of the SlideAnimation is based on a general Animation class, which we extend and then Override the transformation.
public SlideAnimation(View view, int duration) {
//Set the duration of the animation to the int we passed in
setDuration(duration);
//Set the view to be animated to the view we passed in
viewToBeAnimated = view;
//Get the Margin Parameters for the view so we can edit them
viewMarginParams = (MarginLayoutParams) view.getLayoutParams();
//If the view is VISIBLE, hide it after. If it's GONE, show it before we start.
hideAfter = (view.getVisibility() == View.VISIBLE);
//First off, start the margin at the bottom margin we've already set.
//You need your layout to have a negative margin for this to work correctly.
marginStart = viewMarginParams.bottomMargin;
//Decide if we're expanding or collapsing
if (marginStart == 0){
marginEnd = 0 - view.getHeight();
}
else {
marginEnd = 0;
}
//Make sure the view is visible for our animation
view.setVisibility(View.VISIBLE);
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
if (interpolatedTime < 1.0f) {
// Setting the new bottom margin to the start of the margin
// plus the inbetween bits
viewMarginParams.bottomMargin = marginStart
+ (int) ((marginEnd - marginStart) * interpolatedTime);
// Request the layout as it happens so we can see it redrawing
viewToBeAnimated.requestLayout();
// Make sure we have finished before we mess about with the rest of it
} else if (!alreadyFinished) {
viewMarginParams.bottomMargin = marginEnd;
viewToBeAnimated.requestLayout();
if (hideAfter) {
viewToBeAnimated.setVisibility(View.GONE);
}
alreadyFinished = true;
}
hideAfter = false;
}
}
EDIT: If anyone had used this code before and found that if you click on the button that starts the animation more than once before the animation was finished, it would mess up the animation from then on, causing it to always hide the view after the animation finished. I missed the reset of the hideAfter boolean near the bottom of the code, added it now.
you can do this manually by using setvisibility feature on the event onClick()
or
use this
dynamically adding two views one below other

Categories

Resources