Android Custom Controls

Source: Internet
Author: User

In the process of development, sometimes we will encounter some of the Android system's own controls can not solve our needs, such as our development projects in the display of the picture carousel, when we show do not want to distort the picture, but also to ensure that the picture can be fully displayed, how do we do? If it's just a simple imageview control I'm afraid it's hard to implement! Some people will say that ImageView's ScaleType attribute can solve the problem of image filling dissatisfaction, but then the picture is easily distorted, not to the original needs of the product. First, let's take a look at some of the values of the ScaleType property of ImageView. When we look at the source code of the ImageView ScaleType, we will find some of ScaleType's enumeration values, that is, the property values we use

publicstaticenum ScaleType {        CENTER,        CENTER_CROP,        CENTER_INSIDE,        FIT_CENTER,        FIT_END,        FIT_START,        FIT_XY,        MATRIX;        privateScaleType() {        }    }

So let's see how these values are used in the order of the enumeration values.
Android:scaletype= "Center"
Center is centered, according to the original size of the picture to display, when the picture long/wide than the length/width of the view, then the center portion of the image is displayed, the purpose is to let the picture center.
Android:scaletype= "Centercrop"
This is a scaled image, its role is to let the picture scale, but the only drawback is that the image of the zoom will cause a certain crop (when the width of the view set and the width of the picture is different). The picture is still centered
Android:scaletype= "Centerinside"
Display the contents of the picture in full, by scaling it down or the original size to make the picture long/wide equal to or less than the length/width of the view
Android:scaletype= "Fitcenter"
Enlarges/shrinks the image to the width of the view, centered on the display
Android:scaletype= "Fitend"
Enlarges/shrinks the image to the width of the view, displayed in the lower part of the view
Android:scaletype= "Fitstart"
Enlarges/shrinks the image to the width of the view, displayed in the upper part of the view
Android:scaletype= "Fitxy"
The image is not scaled up/down to match the size of the view, this is also the most likely to produce image distortion
Android:scaletype= "Matrix"
Use a matrix to draw, zoom in and out to display the image dynamically
As above

Introduction of the above ScaleType after the beginning to enter our topic, the above attribute value is afraid sometimes can not meet our demand it, more or less can not reach the picture is not distorted and so proportional display effect bar. Some people will say, I can be based on the width of the picture and then set the width of the control, ah, this is to solve the image distortion and proportional display effect, you directly with
' Android:layout_width= ' Wrap_content "
android:layout_height= "Wrap_content"
Isn't that better? But do you think that the picture will reach the picture effect of the carousel diagram? The picture of the carousel is generally filled with the width of the screen, but what about the height? Some people say I can solve the height of the control by multiplying the height of the picture by the ratio of the screen width/picture width of my phone. But there's a problem with that, your phone screen is perfect, but can you make sure it's the same if you go to another phone? I'm afraid not! So how do we fix it? We need to customize a control if we want the perfect display on all phones.
Android custom controls require some custom properties, we need to create a new XML file under App\src\main\res\values named Attrs that is the property file, In the file we're going to use declare-styleable to declare some properties of our own format.

<?xml version= "1.0" encoding= "Utf-8"?     <resources ;  <declare-styleable  name  = "CustomLayout" ;  <attr  name  =" test " format  = "string" ;     </attr ;  </declare-styleable ;  </resources ;   

The name value in declare-styleable name= "customlayout" is preferably the same as our custom control name, name= "test" format= "string", Name is based on your own habits but to do so, just like layout_width let people know the layout of the width of the same. Format is the form of the data, which has 10 formats-string, float, Boolean, Color, dimension, enum, flag, fraction, integer, reference-this time only uses the format float. Because you want to achieve proportional scaling of the picture, you need to use a scale content as follows

<?xml version= "1.0" encoding= "Utf-8"?     <resources ;  <declare-styleable  name  = "CustomLayout" ;  <attr  name  =" ratio " format  = "float" ;  attr ;  </ Declare-styleable ;  </resources  > 

The

Custom control needs to override the Onmeasure method, Onmeasure is used to calculate the width of the control, and when we know the width or height of the control want to set the height or width according to the scale, we need to do the measurement calculation in this method. In the Onmeasure method, we see two parameters onmeasure (int widthmeasurespec, int heightmeasurespec), onmeasure incoming two parameters are the size passed in by the previous control, there are many cases, When overriding the method, you need to calculate the actual size of the control, and then call setmeasureddimension (int, int) to set the actual size. Widthmeasurespec is actually the width of the breadth of the value and width of the pattern, when it comes to the pattern we should be very familiar with, there are three modes are: Measurespec.at_most, measurespec.exactly, Measurespec.unspecified. When the pattern is measurespec.at_most, it means that the size of the control generally changes with the control's subspace or content, and the size of the control is as long as it does not exceed the maximum allowable size of the parent control, which is the pattern that we often use for wrap_content. When the pattern is measurespec.exactly, it is stated that the size of the control is the exact value, we can set this mode when we know the size, and the match_parent we often use is this pattern. When the pattern is measurespec.unspecified, the size of the control is indeterminate, the size of the control can be arbitrarily changed, and we typically use a parent control that is adapter by the size passed in to determine this pattern. So what's the value of the widthmeasurespec inside, and here's the one I printed. The value of Widthmeasurespec when the width of the control is match_parent, which is the mode measurespec.exactly

10-2812:55:50.7855350-5350/custom.lyxrobert.com.customcontrols I/System.out: widthMeasureSpec------>1073742904

So what does 1073742904 mean?

10000111000 of them converted to 10 binary is 1080 is my phone's screen width, then? 01000000000000000000010000111000? What is the situation in front of it?

 public  static  final  int  AT_MOST    =-2147483648 ; public  static  final  int     exactly = 1073741824 ; public  static  final  int  UNSPECIFIED = 0 ;  

1073741824 of the binary is? 01000000000000000000000000000000? See here than everyone knows what's going on.
Then we can get the width method according to Widthmeasurespec we want is measurespec.getsize (widthmeasurespec), the height is the same but the parameters passed in is Heightmeasurespec.
If we know the width and height is also not good, if the user wants to set a certain value of the image padding what to do? For example, padding is 10, then the internal margin of the picture will be 10, the picture before the proportion is difficult to maintain. So we do this to prevent this from happening or by getting the corresponding padding value. The width of the picture is int img_width=width-getpaddingleft ()-getpaddingright (); The height of the picture is obtained by width/calculated aspect ratio int img_height = (int) ( Imagewidth/ratio + 0.5f); but this is still not possible, because the width of the picture is reduced by 10, and the height, although the proportion is reduced, but the effect of the display is probably only the picture of the left and right of the spacing and up and down will have different effects

When the picture is not set padding

When the picture is set to 20DP padding

We found that the top and bottom margin of the picture is not what we set, then if this effect is achieved, we need to get the value of the img_height, plus the padding value of bottom. Height = img_height + Getpaddingtop () + Getpaddingbottom (); The picture after setting is displayed as

 PackageCustom.lyxrobert.com.customcontrols;ImportAndroid.content.Context;ImportAndroid.content.res.TypedArray;ImportAndroid.util.AttributeSet;ImportAndroid.widget.FrameLayout;/** * Created by Ytx on 2016/10/28. * * Public  class customlayout extends framelayout {    Private floatRatio Public CustomLayout(Context context) {Super(context); } Public CustomLayout(context context, AttributeSet attrs) {Super(context, attrs);        TypedArray ta = context.obtainstyledattributes (attrs,r.styleable.customlayout); Ratio = Ta.getfloat (R.styleable.customlayout_rario,-1);    Ta.recycle (); } Public CustomLayout(context context, AttributeSet attrs,intDEFSTYLEATTR) {Super(Context, attrs, defstyleattr); }@Override    protected void onmeasure(intWidthmeasurespec,intHEIGHTMEASURESPEC) {intwidth = measurespec.getsize (widthmeasurespec);//Get Width value        intWidthmode = Measurespec.getmode (Widthmeasurespec);//Get width mode        intHeightintHeightmode = Measurespec.getmode (Heightmeasurespec);//Get height mode        if(Widthmode = = measurespec.exactly && heightmode! = measurespec.exactly && ratio >0) {intImg_width = Width-getpaddingleft ()-getpaddingright ();intImg_height = (int) (Img_width/ratio +0.5f);            Height = img_height + getpaddingtop () + Getpaddingbottom ();        Heightmeasurespec = Measurespec.makemeasurespec (height, measurespec.exactly); }//According to the latest height measurement controls        Super. Onmeasure (Widthmeasurespec, Heightmeasurespec); }}

The layout file is, If you want to add margin to the picture, please add it in custom.lyxrobert.com.customcontrols.CustomLayout, do not set it in ImageView, otherwise it will not work, because our calculation is in CustomLayout Onmea The sure method is implemented inside. lyxrobert:rario= "1.7" inside of 1.7 is the width and height of the picture pixel ratio

<?xml version= "1.0" encoding= "Utf-8"?><linearlayout xmlns:android="Http://schemas.android.com/apk/res/android"  Xmlns:lyxrobert= "http://schemas.android.com/apk/res-auto"android:layout_width=" Match_parent "android:layout_height=" Match_parent "android:orientation=  "Vertical" >                    <custom.lyxrobert.com.customcontrols.CustomLayoutandroid:layout_width="Match_ Parent "android:layout_height=" Wrap_content "lyxrobert:rario="1.7 ">                 <ImageViewandroid:layout_width="Match_parent"android:layout_height ="Match_parent"android:src="@drawable/test" />                        </custom.lyxrobert.com.customcontrols.CustomLayout></linearlayout>

Click Free Download Source code
Please leave a message if you have any questions

Android Custom Controls

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.