Extending View class and layouts in Android - android

I am playing with layouts and views in Android. My layout looks like:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.mycode.MyView
android:id="#+id/MyView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
<LinearLayout
android:id="#+id/leftpane"
android:layout_width="55dp"
android:layout_height="wrap_content"
android:layout_weight="0.95"
android:background="#color/leftpane_background"
android:gravity="center"
android:orientation="vertical"
android:scrollbarStyle="insideOverlay" >
</LinearLayout>
</LinearLayout>
If i comment the lines <com.mycode.MyView .... />, the left linear layout (with id leftpane) is showed, otherwise not. If i add another layout after the leftpane layout (for example a scroll view layout), it does not get showed as well.
Why using my custom view (MyView) makes disappear all other layouts?
What i would like to do is to have my custom View for the background of the application, where i would show images, and some other view over the background, like scroll views, buttons and so on.
This is the code of MyView class. Keep in mind that i need to draw on the background of the activity an images (on the whole background, obviously not including the action bar):
/**
*/
class MyView extends View
{
TextPaint text_paint;
Paint paint;
private void InitView()
{
text_paint = new TextPaint( Paint.ANTI_ALIAS_FLAG );
text_paint.setColor( Color.BLACK );
paint = new Paint();
}
public MyView(Context context)
{
super(context);
InitView();
}
public MyView(Context context, AttributeSet attrs)
{
super(context, attrs);
InitView();
}
public MyView(Context context, AttributeSet attrs, int defaultStyle)
{
super(context, attrs, defaultStyle);
InitView();
}
#Override
protected void onDraw( Canvas canvas )
{
super.onDraw(canvas);
//int w, h;
//w = canvas.getWidth();
//h = canvas.getHeight();
//paint.setColor( Color.WHITE );
//canvas.drawRect(0, 0, w-1, h-1, paint );
//canvas.drawText( "ciao", 100, 100, text_paint);
}
};

Try to change your view's height as:
android:layout_height="wrap_content"

Maybe you did some error work when you overrode the onMeasure method in your custom MyView,
and so the MyView's match all the parent view.
Can you show your code which in the onLayout and onMeasure method of the MyView.

Related

Adding text hint to Android SwipeRefreshLayout

How do I add a hint on the top of a listView like "Pull down to refresh" which is contained in a swipeRefreshLayout from android.support.v4.
The pull down to refresh works but I want to add a text whenever the user pulls the listview slightly down.
EDIT 10/21/2014
If you update the support-v4 to the latest version (at least 21.0.0) you can use the built-in loading indicator!
I just came up with a simple, yet effective, solution.
The idea is to add a custom ViewGroup that grows its height when the SwipeRefreshLayout child gets pulled down. In this ViewGroup you will put everything you need for your hint (TextViews, ImageViews, ...).
I chose to extend a RelativeLayout because it makes easier to position your "hint" elements.
1) Create a custom widget as follows:
public class SwipeRefreshHintLayout extends RelativeLayout {
public SwipeRefreshHintLayout(Context context) {
super(context);
}
public SwipeRefreshHintLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SwipeRefreshHintLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setSwipeLayoutTarget(final SwipeRefreshLayout swipeRefreshLayout) {
final View swipeTarget = swipeRefreshLayout.getChildAt(0);
if (swipeTarget == null) {
return;
}
swipeTarget.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
private Rect oldBounds = new Rect(), newBounds = new Rect();
#Override
public boolean onPreDraw() {
newBounds.set(swipeTarget.getLeft(), swipeRefreshLayout.getTop(), swipeTarget.getRight(), swipeTarget.getTop());
if (!oldBounds.equals(newBounds)){
getLayoutParams().height = newBounds.height();
requestLayout();
oldBounds.set(newBounds);
}
return true;
}
});
}
}
2) In your Fragment or Activity layout use this custom widget.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.widget.SwipeRefreshHintLayout
android:id="#+id/swipe_hint"
android:layout_width="match_parent"
android:layout_height="0dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="#string/label_swipe_to_refresh"/>
<!-- Any other view positioned using RelativeLayout rules -->
</com.example.widget.SwipeRefreshHintLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
3) Then, in your Activity onCreate() or in your Fragment onCreateView(), put those lines:
mSwipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipe_container);
mSwipeRefreshHintLayout = (SwipeRefreshHintLayout) rootView.findViewById(R.id.swipe_hint);
mSwipeRefreshHintLayout.setSwipeLayoutTarget(mSwipeRefreshLayout);
Done!

How to draw ImageView on ImageView?

I have an ImageView and I would like to draw dinamically another images on my base ImageView.
In this image for example I have a tree and I would like to draw image of people
Any suggestions to start?
yes my problem is like #Tsunaze say:
I have a tree, and I want to put heads on it,
XML :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/iv_tree"
android:scaleType="fitXY"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:adjustViewBounds="true"
android:src="#drawable/my_tree" />
</RelativeLayout>
MyView.java :
public MyView extends View{
private Bitmap head_1, head_2;
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
init();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
public MyView(Context context) {
super(context);
this.context = context;
init();
}
private void init(){
head_1= BitmapFactory.decodeResource(context.getResources(),
R.drawable.head_1);
head_2= BitmapFactory.decodeResource(context.getResources(),
R.drawable.head_2);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(head_1, coordinateX_head_1, coordinateY_head_1, null);
canvas.drawBitmap(head_2, coordinateX_head_2, coordinateY_head_2, null);
}
}
You choose the coordinate you want, you can even use function like canvas.getWidth() or canvas.getHeight(). Pose yourself as a painter. Good luck.
What you have to do is create a class that extends from ImageView, set the default parameters that you want as usual and override the on draw method, this method will give you the chance to get a reference to the canvas and draw bitmaps or pretty much anything you want, but remember to call first super.onDraw to keep your default configuration and overlay your new images.
There's plenty of tutorials on how to use canvas, so now you have the proper path to take, hope this helps.
Regards
setBackgroundResource to ImageView and use setImageResource over it.
Ex :
imageView.setBackgroundResource(R.id.backgroundTree);
imageView.setImageResource(R.id.allPeople);
EDIT :
If you want multiple images to be overlayed, check this example.
You can also use RelativeLayout and add ImageView inside it programmatically.
<RelativeLayout>
<ImageView/>
<ImageView/>
<ImageView/>
<ImageView/>
</RelativeLayout>

Draw lines between ListView rows

I have ListView with ImageView in rows.
I need to draw lines between these ImageViews.
So one line is started at first row at ImageView position and ends at second row at ImageView position. And so on.
What is the best way to draw these lines?
Thank you.
UPDATE. I am sorry, I can't upload image and I speak english not very well.
It is not horizontal divider between rows. If to simplify it: line starts at vertical center of one row at ImageView position and ends with vertical center of next row at ImageView position.
I think I should try:
To override row view.
At Adapter's GetView where I create row view pass to this row view coordinates of adjacent rows.
In view's onDraw method calculate coordinates and draw line.
To override ListView. In it's OnDraw method try to get ImageView's positions and draw all lines.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ListView
android:id="#+id/android:list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:divider="#FFCC00"
android:dividerHeight="4px"/>
</LinearLayout>
Have a listview seperator.
I am not sure if I understood your question correctly, but this should make really nice gradient lines between rows :
mListView = getListView();
mAdapter = new ServersListAdapter(this, new String[] {},
new String[] {}, new String[] {});
int[] colors = { Color.parseColor("#D3D3D3"), Color.parseColor("#D3D3D3"), Color.parseColor("#D3D3D3") };
mListView.setDivider(new GradientDrawable(Orientation.RIGHT_LEFT, colors));
This is an example of a view you can draw a line in. Create this class, refresh your palette if you need to.
public class LineTextView extends AppCompatTextView {
private Paint paint = new Paint();
public LineTextView(Context context) {
super(context);
}
public LineTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LineTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.parseColor("#000000"));
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.FILL);
canvas.drawLine(0, 0, 0, getHeight(), paint);
}
}
Now you can use it in your layout
<LinearLayout
android:layout_width="2dp"
android:layout_height="match_parent"
android:orientation="vertical">
<com.example.taskmodel.view.LineTextView
android:id="#+id/lineTextViewTopHalf"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:visibility="invisible"/>
<com.example.taskmodel.view.LineTextView
android:id="#+id/lineTextViewBottomHalf"
android:layout_width="2dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>

Android: Drawing shapes programmatically on a View in layout

The documentation about this is really confusing. I simply need to add rectangels to a View I defined in my main.xml layout file. It will be a small part of the layout.
What I want to achieve is, I want to add shelves to a room but since the room shape and shelves change, I need to add them programmatically.
Below is a little part of my main.xml file, you can see the View I defined:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="#+id/relativeLayout2"
android:layout_width="600dp"
android:layout_height="650dp"
android:layout_marginTop="70dp"
android:layout_marginLeft="30dp"
android:layout_toRightOf="#+id/relativeLayout1" >
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="#string/getDirections"
android:textSize="20dp"
android:textStyle="bold" />
<View
android:id="#+id/roomplan"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/textView3"
android:layout_marginTop="40dp"
android:background="#android:color/white" />
</RelativeLayout>
This is the custom View class I created to handle dynamic changes:
public class CustomView extends View {
ShapeDrawable roomFrame;
ArrayList<ShapeDrawable> shelfFrames;
public CustomView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
roomFrame.draw(canvas);
for (ShapeDrawable shelfFrame : shelfFrames){
shelfFrame.draw(canvas);
}
}
public void setRoom(Stage stage){
roomFrame = new ShapeDrawable(new RectShape());
roomFrame.getPaint().setColor(0xff74AC23);
roomFrame.setBounds(10, 10, stage.getWidth(), stage.getHeight());
}
public void setShelves(ArrayList<Shelf> shelves){
shelfFrames = new ArrayList<ShapeDrawable>();
for(int i = 0; i<shelves.size(); i++){
ShapeDrawable shelfFrame = new ShapeDrawable(new RectShape());
shelfFrame.getPaint().setColor(0xff74AC23);
shelfFrame.setBounds(shelves.get(i).getXPosition(), shelves.get(i).getYPosition(), shelves.get(i).getWidth(), shelves.get(i).getHeight());
shelfFrames.add(shelfFrame);
}
}
}
Now simply, when a new room plan is asked I am trying to assign this class to the View object in the xml layout:
public void loadRoomPlan(Room room, ArrayList<Shelf> shelves){
CustomView asdsView = (CustomView)findViewById(R.id.roomplan);
asdsView.setRoom(room);
asdsView.setShelves(shelves);
asdsView.invalidate();
}
I always get
Caused by: java.lang.ClassCastException: android.view.View cannot be cast to org.example.myproject.CustomView
error.
Probably I am doing this very very wrong, am I not?
The error seems to be in this line:
CustomView asdsView = (CustomView)findViewById(R.id.shopplan);
What is shopplan? In case it is a mistake and you meant R.id.roomplan try to subtitute the View in your layout for your Custom view:
<org.example.myproject.CustomView
android:id="#+id/roomplan"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/textView3"
android:layout_marginTop="40dp"
android:background="#android:color/white" />
UPDATE:
Try adding the other two constructors to your CustomView class:
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
When you use a custom view in an xml layout, your view has to deal with the layout attributes (the constructor AttributeSet param).

How to scroll bitmaps?

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.

Categories

Resources